package com.nq.service.impl;

/**

 * 开发者----股牛网络

 * 联系TG：gncms

 */

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.nq.activaity.entity.StIntegralTask;
import com.nq.activaity.entity.StUserIntegralRecord;
import com.nq.activaity.entity.StUserInviteRecord;
import com.nq.common.LoginType;
import com.nq.common.ServerResponse;
import com.nq.common.SystemVersionEnum;
import com.nq.common.UserIntegralTypeEnum;
import com.nq.common.entity.StStockTickerDetails;
import com.nq.common.entity.info.StockTickerListInfo;
import com.nq.config.StockPoll;
import com.nq.dao.*;
import com.nq.dao.activaity.StIntegralTaskMapper;
import com.nq.dao.activaity.StUserIntegralRecordMapper;
import com.nq.dao.activaity.StUserInviteRecordMapper;
import com.nq.dao.stock.StStockMapper;
import com.nq.dao.stock.StStockTickerMapper;
import com.nq.dao.stock.StUserLevelMapper;
import com.nq.pojo.*;
import com.nq.service.*;
import com.nq.stock.entity.StStock;
import com.nq.stock.entity.StStockTicker;
import com.nq.stock.entity.StUserLevel;
import com.nq.stock.vo.StUserLevelVo;
import com.nq.utils.DateTimeUtil;
import com.nq.utils.KeyUtils;
import com.nq.utils.PropertiesUtil;
import com.nq.utils.SymmetricCryptoUtil;
import com.nq.utils.ip.IpUtils;
import com.nq.utils.ip.JuheIpApi;
import com.nq.utils.redis.CookieUtils;
import com.nq.utils.redis.JsonUtil;
import com.nq.utils.redis.RedisShardedPoolUtils;
import com.nq.utils.task.tsanghi.StocksComponent;
import com.nq.vo.agent.AgentUserListVO;
import com.nq.vo.futuresposition.FuturesPositionVO;
import com.nq.vo.indexposition.IndexPositionVO;
import com.nq.vo.position.PositionProfitVO;
import com.nq.vo.position.PositionVO;
import com.nq.vo.user.UserInfoVO;
import com.nq.vo.user.UserSuperiorAndSubordinateVO;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service("iUserService")
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);

    @Value("${spring.profiles.active}")
    private String active;
    /**
     * 记录递归执行次数
     * 不能超过3次
     */
    private static int count = 0;

    @Autowired
    UserMapper userMapper;
    @Autowired
    private UserCashDetailMapper userCashDetailMapper;
    @Autowired
    private UserWithdrawMapper userWithdrawMapper;
    @Autowired
    private IUserService iUserService;
    @Autowired
    IAgentUserService iAgentUserService;

    @Autowired
    ISiteLoginLogService iSiteLoginLogService;

    @Autowired
    StockOptionMapper stockOptionMapper;

    @Autowired
    StockMapper stockMapper;
    @Autowired
    IUserPositionService iUserPositionService;
    @Autowired
    IUserBankService iUserBankService;
    @Autowired
    AgentUserMapper agentUserMapper;
    @Autowired
    SiteTaskLogMapper siteTaskLogMapper;
    @Autowired
    IStockOptionService iStockOptionService;
    @Autowired
    ISiteSettingService iSiteSettingService;
    @Autowired
    IUserCashDetailService iUserCashDetailService;
    @Autowired
    IUserRechargeService iUserRechargeService;
    @Autowired
    IUserWithdrawService iUserWithdrawService;
    @Autowired
    IUserIndexPositionService iUserIndexPositionService;
    @Autowired
    ISiteIndexSettingService iSiteIndexSettingService;
    @Autowired
    StockPoll stockPoll;
    @Autowired
    SiteAmtTransLogMapper siteAmtTransLogMapper;
    @Autowired
    IUserFuturesPositionService iUserFuturesPositionService;
    @Autowired
    ISiteFuturesSettingService iSiteFuturesSettingService;
    @Autowired
    IStockFuturesService iStockFuturesService;
    @Autowired
    StockFuturesMapper stockFuturesMapper;
    @Autowired
    StockIndexMapper stockIndexMapper;
    @Autowired
    ISiteMessageService iSiteMessageService;
    @Resource
    private UserRechargeMapper userRechargeMapper;
    @Resource
    private StUserLevelMapper userLevelMapper;
    @Resource
    private StStockMapper stStockMapper;
    @Resource
    private StStockTickerMapper stStockTickerMapper;
    @Resource
    private StocksComponent stocksComponent;
    @Autowired
    private IUserUsdtService userUsdtService;
    @Resource
    private IStUserLevelService stUserLevelService;
    @Resource
    private FundsApplyMapper fundsApplyMapper;
    @Resource
    private StUserIntegralRecordMapper userIntegralRecordMapper;

    @Resource
    private StUserInviteRecordMapper userInviteRecordMapper;

    @Resource
    private StIntegralTaskMapper integralTaskMapper;

    /**
     * 密码次数超过5次，则自动锁定半个小时
     * @param prefix
     * @param userId
     * @return
     */
    @Override
    public boolean isLocked(String prefix, Integer userId) {
        String key = prefix + userId;
        Long retryCount = RedisShardedPoolUtils.exists(key) ? RedisShardedPoolUtils.incr(key) : 0L;
        if (retryCount > User.MAX_RETRY) {
            RedisShardedPoolUtils.expire(key, User.LOCK_TIME); // 超过最大尝试次数后锁定用户
            return true;
        }
        if (retryCount == 1L) {
            RedisShardedPoolUtils.expire(key, User.MAX_RETRY - 1); // 设置剩余允许次数
        }
        return false;
    }

    @Transactional(rollbackFor = Exception.class)
    public ServerResponse reg(String yzmCode, String code, String agentCode, String regType, String account, String userPwd, String country, Integer inviteCode, HttpServletRequest request) {
        if (StringUtils.isBlank(regType) || StringUtils.isBlank(account) ||
                StringUtils.isBlank(userPwd)) {
            return ServerResponse.createByErrorMsg("Registration failed, parameters cannot be empty");
        }

        // 校验手机区号
        if (LoginType.PHONE.getCode().equals(regType)) {
            if (StringUtils.isBlank(code)) {
                return ServerResponse.createByErrorMsg("Registration failed, phone area code cannot be empty");
            }
        }

        // 校验邮箱国家
        if (LoginType.EMAIL.getCode().equals(regType)) {
//            if (StringUtils.isBlank(yzmCode)) {
//                return ServerResponse.createByErrorMsg("Registration failed, yzmCode cannot be empty");
//            }
            if (StringUtils.isBlank(country)) {
                return ServerResponse.createByErrorMsg("Registration failed, country cannot be empty");
            }
        }
        if(LoginType.ACCOUNT.getCode().equals(regType)){
            // 使用正则表达式过滤特殊字符
            Pattern pattern = Pattern.compile("[\\s@#$%^&*()+=|<>?{}\\[\\]~-]");
            Matcher matcher = pattern.matcher(account);
            if (matcher.find()) {
                return ServerResponse.createByErrorMsg("Registration failed. Account cannot contain special characters");
            }

        }

        // 新增User实体类
        User user = new User();

        if (StringUtils.isNotBlank(agentCode)) {
            AgentUser agentUser = this.iAgentUserService.findByCode(agentCode.trim());
            log.error("==========agentCode:{},==============agentUser:{}", agentCode, agentUser);
            if (agentUser == null) {
                return ServerResponse.createByErrorMsg("注册失败，代理不存在");
            }
            if (agentUser.getIsLock().intValue() == 1) {
                return ServerResponse.createByErrorMsg("注册失败，代理已锁定");
            }

            user.setAgentId(agentUser.getId());
            user.setAgentName(agentUser.getAgentName());
        }


        User dbuser = this.userMapper.findByPhoneOrEmail(account);
        if (dbuser != null) {
            String regTypeMsg = "";
            if(LoginType.PHONE.getCode().equals(regType)){
                regTypeMsg = "手机号";
            }else if(LoginType.EMAIL.getCode().equals(regType)){
                regTypeMsg = "邮箱";
            }else if(LoginType.ACCOUNT.getCode().equals(regType)){
                regTypeMsg = "账号";
            }
            return ServerResponse.createByErrorMsg("注册失败，"+regTypeMsg+"已注册");
        }

        // 校验不通过直接返回
//        ServerResponse serverResponse = checkYzmCode(regType, yzmCode, code, account);
//        if (!serverResponse.isSuccess()) {
//            return serverResponse;
//        }


        if (LoginType.PHONE.getCode().equals(regType)) {
            user.setPhone(account);
            user.setCode(code);
        } else if (LoginType.EMAIL.getCode().equals(regType)) {
            user.setCountry(country);
            user.setEmail(account);
        }else if(LoginType.ACCOUNT.getCode().equals(regType)){
            user.setRecomPhone(account);
        }

        user.setUserPwd(SymmetricCryptoUtil.encryptPassword(userPwd));
        user.setAccountType(Integer.valueOf(regType));
        user.setIsLock(Integer.valueOf(1));
        user.setIsActive(Integer.valueOf(0));

        user.setRegTime(new Date());
        String uip = IpUtils.getIp(request);
        user.setRegIp(uip);
        String uadd = JuheIpApi.ip2Add(uip);
        user.setRegAddress(uadd);

        user.setIsLogin(Integer.valueOf(0));

        user.setUserAmt(new BigDecimal("0"));
        user.setEnableAmt(new BigDecimal("0"));

        user.setUserIndexAmt(new BigDecimal("0"));
        user.setEnableIndexAmt(new BigDecimal("0"));

        user.setUserFutAmt(new BigDecimal("0"));
        user.setEnableFutAmt(new BigDecimal("0"));

        user.setTradingAmount(new BigDecimal("0"));
        user.setSumBuyAmt(new BigDecimal("0"));
        user.setSumChargeAmt(new BigDecimal("0"));
        user.setDjzj(new BigDecimal("0"));

        this.userMapper.insert(user);

        // 校验是否有用户邀请码
        if (null != inviteCode) {
            User referUser = userMapper.selectById(inviteCode);
            if (null == referUser) {
                return ServerResponse.createByErrorMsg("邀请人不存在.");
            }

            log.info("========================用户ID：" + user.getId());
            log.info("========================邀请人ID：" + referUser.getId());

            // 邀请奖励
            inviteRewards(user.getId(), referUser.getId());
        }
        return ServerResponse.createBySuccessMsg("注册成功，请登录");
    }

    private void inviteRewards(Integer userId, Integer referId){
        // 插入邀请表
        StUserInviteRecord inviteRecord = new StUserInviteRecord();
        inviteRecord.setUserId(userId);
        inviteRecord.setReferId(referId);
        inviteRecord.setCreateTime(new Date());
        inviteRecord.setUpdateTime(new Date());
        inviteRecord.setStatus(1);
        inviteRecord.setRewardMount(BigDecimal.ZERO);
        inviteRecord.setRewardPoints(0);
        userInviteRecordMapper.insert(inviteRecord);

        // 获取任务列表
        LambdaQueryWrapper<StIntegralTask> taskLambdaQueryWrapper = new LambdaQueryWrapper<>();
        taskLambdaQueryWrapper.eq(StIntegralTask::getTaskType, StIntegralTask.TASK_TYPE_INVITATION);
        List<StIntegralTask> integralTaskList = integralTaskMapper.selectList(taskLambdaQueryWrapper);
        for (StIntegralTask integralTask : integralTaskList) {
            int maxNum = integralTask.getMaxNum();
            // 查询邀请人数
            LambdaQueryWrapper<StUserInviteRecord> inviteRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
            inviteRecordLambdaQueryWrapper.eq(StUserInviteRecord::getReferId, referId);
            Long count = userInviteRecordMapper.selectCount(inviteRecordLambdaQueryWrapper);
            if (maxNum == count.intValue()){
                // 更新用户积分
                updateUserIntegral(referId, integralTask.getIntegral(), UserIntegralTypeEnum.USER_INVITATION.getDesc(), true, integralTask.getId());

                // 更新用户邀请表的积分
                inviteRecord.setRewardPoints(integralTask.getIntegral());
                inviteRecord.setId(inviteRecord.getId());
                userInviteRecordMapper.updateById(inviteRecord);
            }
        }

    }


    /**
     * 注册-校验验证码
     * @param type
     * @param yzmCode
     * @param account
     * @return
     */

    public ServerResponse checkYzmCode(String type, String yzmCode, String code, String account){
        if (LoginType.PHONE.getCode().equals(type)) {
            if (StringUtils.isBlank(code)) {
                return ServerResponse.createByErrorMsg("check failure, phone area code cannot empty");
            }
            String key = "V_PHONE_CODE_" + code + "_" + account;
            String phoneCode = RedisShardedPoolUtils.get(key);
            if (!yzmCode.equals(phoneCode)) {
                return ServerResponse.createByErrorMsg("注册失败、验证码错误");
            }
        } else {
            String key = "V_MAIL_CODE_" + account;
            String mailCode = RedisShardedPoolUtils.get(key);;
            if (!yzmCode.equals(mailCode)) {
                return ServerResponse.createByErrorMsg("注册失败、验证码错误");
            }
        }
        return ServerResponse.createBySuccess("The verification is successful.");
    }


    /**
     * 忘记密码-校验验证码
     * @param type
     * @param yzmCode
     * @param account
     * @return
     */

    public ServerResponse checkForgetYzmCode(String type, String yzmCode, String code, String account){
        if (LoginType.PHONE.getCode().equals(type)) {
            if (StringUtils.isBlank(code)) {
                return ServerResponse.createByErrorMsg("check failure, phone area code cannot empty");
            }
            String key = "V_FORGET_PHONE_CODE_" + code + "_" + account;
            String phoneCode = RedisShardedPoolUtils.get(key);
            if (!yzmCode.equals(phoneCode)) {
                return ServerResponse.createByErrorMsg("check failure, verification code error");
            }
        } else {
            String key = "V_FORGET_MAIL_CODE_" + account;
            String mailCode = RedisShardedPoolUtils.get(key);
            if (!yzmCode.equals(mailCode)) {
                return ServerResponse.createByErrorMsg("Registration failure, verification code error");
            }
        }
        return ServerResponse.createBySuccess("The verification is successful.");
    }


    public ServerResponse login(String loginType, String code, String account, String userPwd, String country, HttpServletRequest request) {
        // 判断是手机号登陆还是邮箱登录
        if (StringUtils.isBlank(loginType)) {
            return ServerResponse.createByErrorMsg("Please enter the login type");
        }
        if (StringUtils.isBlank(account) || StringUtils.isBlank(userPwd)) {
            return ServerResponse.createByErrorMsg("Phone/Email number cannot be empty");
        }
        // 校验手机区号
        if (LoginType.PHONE.getCode().equals(loginType)) {
            if(StringUtils.isBlank(code)) {
                return ServerResponse.createByErrorMsg("phone area code cannot be empty");
            }
        }
        // 校验邮箱的国家
        if (LoginType.EMAIL.getCode().equals(loginType)) {
            if(StringUtils.isBlank(country)) {
                return ServerResponse.createByErrorMsg("country cannot be empty");
            }
        }

        // 校验账号的密码
        if (LoginType.ACCOUNT.getCode().equals(loginType)) {
            if(StringUtils.isBlank(userPwd)){
                return ServerResponse.createByErrorMsg("password cannot be empty");
            }
        }

        userPwd = SymmetricCryptoUtil.encryptPassword(userPwd);
        User user = this.userMapper.login(loginType, code, account, userPwd, country);
        if (user != null) {
            if (user.getIsLogin().intValue() == 1) {
                return ServerResponse.createByErrorMsg("Login failed, account locked");
            }

            log.info("用户{}登陆成功, 登陆状态{} ,交易状态{}", new Object[]{user.getId(), user.getIsLogin(), user.getIsLock()});

            this.iSiteLoginLogService.saveLog(user, request);
            return ServerResponse.createBySuccess(user);
        }
        return ServerResponse.createByErrorMsg("Login failed, username and password incorrect");
    }


    public User getCurrentUser(HttpServletRequest request) {
        String property = PropertiesUtil.getProperty("user.cookie.name");
//        System.out.println(property);
        String loginToken = request.getHeader(property);
        if (loginToken == null) {
            return null;
        }
        String userJson = RedisShardedPoolUtils.get(loginToken);
        return (User) JsonUtil.string2Obj(userJson, User.class);
    }


    public User getCurrentRefreshUser(HttpServletRequest request) {
        String property = PropertiesUtil.getProperty("user.cookie.name");
        String header = request.getHeader(property);
        if (header == null) {
            return null;
        }

        String userJson = RedisShardedPoolUtils.get(header);
        User user = (User) JsonUtil.string2Obj(userJson, User.class);

        if (user == null) {
            return null;
        } else {
            return this.userMapper.selectById(user.getId());
        }
    }

    @Override
    public ServerResponse queryOptionList(String changePercent,Integer pageNo, Integer pageSize, HttpServletRequest request) {
        User user = getCurrentUser(request);
        if (user == null) {
            return ServerResponse.createByErrorMsg("Please log in first.");
        }
//
//        Integer userId = user.getId();
        PageHelper.startPage(pageNo, pageSize);

        List<StStockTicker> tickerList = stStockTickerMapper.queryOptionList(user.getId(), changePercent);
        PageInfo pageInfo = new PageInfo(tickerList);
        return ServerResponse.createBySuccess(pageInfo);
    }

    @Override
    public int updateTradingAmount(Integer id, BigDecimal tradingAmount, BigDecimal enableAmt) {
        User user = new User();
        user.setId(id);
        user.setTradingAmount(tradingAmount);
        user.setEnableAmt(enableAmt);
        return this.userMapper.updateByPrimaryKeySelective(user);
    }

    @Override
    public ServerResponse getUserLevel(HttpServletRequest request) {
        User user = iUserService.getCurrentRefreshUser(request);
        if (user == null) {
            return ServerResponse.createByErrorMsg("Please log in first.");
        }

        StUserLevelVo levelVo = new StUserLevelVo();
        // 查询用户交易金额  充值金额+买入股票金额+买入基金金额
        Integer userId = user.getId();
        // 获取用户等级
        Integer levelId = stUserLevelService.getUserLevelByUserId(userId);
        // 用户总的交易金额
        BigDecimal transactionAmount = stUserLevelService.getUserTransactionAmountByUserId(userId);
        // 计算下一个等级
        StUserLevel nextLevel = userLevelMapper.queryNextLevel(levelId);
        if (null == nextLevel) {
            nextLevel = userLevelMapper.selectOne(new QueryWrapper<StUserLevel>().orderByDesc("id").last("limit 1"));
        }

        StUserLevel userLevel = userLevelMapper.selectById(levelId);
        if (null == userLevel) {
            levelVo.setName("JVIP1");
        }else {
            BeanUtils.copyProperties(userLevel, levelVo);
        }

        levelVo.setNextLevelId(nextLevel.getId());
        levelVo.setNextLevelName(nextLevel.getName());
        levelVo.setTransactionAmount(transactionAmount);
        levelVo.setNextTransactionAmount(nextLevel.getAmount());
        return ServerResponse.createBySuccess(levelVo);
    }

    @Override
    @Transactional
    public ServerResponse updateAgentAmt(Integer userId, String amt, Integer direction, HttpServletRequest request) {
        if (userId == null || amt == null || direction == null) {
            return ServerResponse.createByErrorMsg("Parameters cannot be empty.");
        }

        User user = this.userMapper.selectByPrimaryKey(userId);
        if (user == null) {
            return ServerResponse.createByErrorMsg("User does not exist");
        }

        BigDecimal user_enable = user.getEnableAmt();

        BigDecimal user_amt_back = new BigDecimal("0");
        BigDecimal user_enable_back = new BigDecimal("0");

        // 入金
        if (direction.intValue() == 0) {
            user_enable_back = user_enable.add(new BigDecimal(amt));

            // 增加充值记录
            UserRecharge userRecharge = new UserRecharge();
            userRecharge.setUserId(user.getId());
            userRecharge.setNickName(user.getRealName());
            userRecharge.setAgentId(user.getAgentId());
            String ordersn = KeyUtils.getRechargeOrderSn();
            userRecharge.setOrderSn(ordersn);
            userRecharge.setOrderDesc("Backstage manual gold deposit");
            userRecharge.setPayChannel("2");
            userRecharge.setPayAmt(new BigDecimal(amt));
            userRecharge.setOrderStatus(Integer.valueOf(1));
            userRecharge.setAddTime(new Date());
            userRecharge.setPayTime(new Date());
            userRecharge.setPayId(0);
            this.userRechargeMapper.insert(userRecharge);

            // 记录资金记录
            UserCashDetail ucd = new UserCashDetail();
            ucd.setAgentId(user.getAgentId());
            ucd.setAgentName(user.getAgentName());
            ucd.setUserId(user.getId());
            ucd.setUserName(user.getRealName());
            String deType = direction.intValue() == 0 ? "Recharge" : "Cash";
            ucd.setDeType(deType);
            ucd.setDeAmt(new BigDecimal(amt));
            ucd.setDeSummary(" Operation " + user.getRealName() + ", " + deType + " " + amt + " ,The amount available to the current user：" + user_enable_back);
            ucd.setAddTime(new Date());
            ucd.setIsRead(Integer.valueOf(0));
            this.userCashDetailMapper.insert(ucd);
        }
        else if (direction.intValue() == 1) {
            // 出金
            if (user_enable.compareTo(new BigDecimal(amt)) == -1) {
                return ServerResponse.createByErrorMsg("The deduction failed, and the available funds were insufficient.");
            }
            // 总余额
            // 可用余额
            user_enable_back = user_enable.subtract(new BigDecimal(amt));

            // 增加提现记录
            UserWithdraw userWithdraw = new UserWithdraw();
            userWithdraw.setUserId(user.getId());
            userWithdraw.setNickName(user.getRealName());
            userWithdraw.setAgentId(user.getAgentId());
            userWithdraw.setWithAmt(new BigDecimal(amt));
            userWithdraw.setApplyTime(new Date());
            userWithdraw.setWithName(user.getRealName());
            userWithdraw.setType(UserWithdraw.MANUAL_TYPE);
            userWithdraw.setWithStatus(UserWithdraw.WITH_STATUS_1);
            userWithdraw.setWithFee(new BigDecimal(0));
            userWithdraw.setTransTime(new Date());
            userWithdrawMapper.insert(userWithdraw);
        } else {
            return ServerResponse.createByErrorMsg("This action does not exist.");
        }
        // 更新用户可用资金
        user.setEnableAmt(user_enable_back);
        this.userMapper.updateByPrimaryKeySelective(user);


        // 记录日志
        String message = direction.intValue() == 0 ? "Recharge" : "Cash";
        SiteTaskLog siteTaskLog = new SiteTaskLog();
        siteTaskLog.setTaskType("System Modified " + message + " Amount");
        StringBuffer cnt = new StringBuffer();
        cnt.append(" Operation " + user.getRealName() + ", Recharge" + amt + " successful,The amount available to the current user：" + user_enable_back);
        siteTaskLog.setTaskCnt(cnt.toString());
        StringBuffer target = new StringBuffer();
        target.append(" Operation " + user.getRealName() + ", Recharge" + amt + " successful,The amount available to the current user：" + user_enable_back);
        siteTaskLog.setTaskTarget(target.toString());
        siteTaskLog.setIsSuccess(Integer.valueOf(0));
        siteTaskLog.setAddTime(new Date());
        int insertCount = this.siteTaskLogMapper.insert(siteTaskLog);
        if (insertCount > 0) {
            return ServerResponse.createBySuccessMsg("Successfully modified funds");
        }
        return ServerResponse.createByErrorMsg("Failed to modify funds");
    }

    @Override
    public ServerResponse authByAgent(Integer userId, Integer state, String authMsg) {
        if (state == null || userId == null) {
            return ServerResponse.createByErrorMsg("Id and state cannot be empty.");
        }

        User user = this.userMapper.selectByPrimaryKey(userId);
        if (user == null) {
            return ServerResponse.createByErrorMsg("This user could not be found.");
        }

        if (state.intValue() == 3) {
            if (StringUtils.isBlank(authMsg)) {
                return ServerResponse.createByErrorMsg("Audit failure information is required");
            }
            user.setAuthMsg(authMsg);
        }

        user.setIsActive(state);
        int updateCount = this.userMapper.updateByPrimaryKeySelective(user);
        if (updateCount > 0) {
            return ServerResponse.createBySuccessMsg("Reviewed Successfully");
        }
        return ServerResponse.createByErrorMsg("Audit failure");
    }

    public ServerResponse addOption(String code, String market, HttpServletRequest request) {
        User user = getCurrentUser(request);
        if (user == null) {
            return ServerResponse.createByErrorMsg("Please log in first.");
        }

        // 股票代码
        String stockCode = code;
        if (StringUtils.isBlank(stockCode)) {
            return ServerResponse.createByErrorMsg("The stock code is empty.!");
        }

        QueryWrapper<StStock> stockQueryWrapper = new QueryWrapper<>();
        stockQueryWrapper.eq("code", stockCode);
        stockQueryWrapper.eq("market", market);
        StStock stStock = stStockMapper.selectOne(stockQueryWrapper);

//        stockCode = stockCode.replace("sh", "").replace("sz", "").replace("bj", "").replace("hk", "").replace("us", "");
//        StockOption dboption = this.stockOptionMapper.findMyOptionIsExistByCode(user.getId(), stockCode);
//
//        if (dboption != null) {
//            return ServerResponse.createByErrorMsg("添加失败，自选股已存在");
//        }
//
//        Stock stock = new Stock();
//        //期货逻辑
//        if (code.contains("hf")) {
//            StockFutures stockFutures = this.stockFuturesMapper.selectFuturesByCode(stockCode);
//            if (stockFutures != null) {
//                stock.setId(stockFutures.getId());
//                stock.setStockCode(stockFutures.getFuturesCode());
//                stock.setStockGid(stockFutures.getFuturesGid());
//                stock.setStockName(stockFutures.getFuturesName());
//                stock.setIsLock(0);
//            }
//        } else if (code.contains("sh") || code.contains("sz") || code.contains("hk") || code.contains("us")) {
//            return ServerResponse.createByErrorMsg("添加失败，指数不支持自选");
////            StockIndex stockIndex = this.stockIndexMapper.selectIndexByCode(stockcode);
////            if(stockIndex != null){
////                stock.setId(stockIndex.getId());
////                stock.setStockCode(stockIndex.getIndexCode());
////                stock.setStockGid(stockIndex.getIndexGid()+"zs");
////                stock.setStockName(stockIndex.getIndexName());
////                stock.setIsLock(0);
////            }
//        } else {
//            stock = this.stockMapper.findStockByCode(code);
//        }
//
        if (null == stStock) {
            return ServerResponse.createByErrorMsg("Failed to add, the stock does not exist.");
        }
        StockOption stockOption = new StockOption();
        stockOption.setUserId(user.getId());
        stockOption.setStockId(stStock.getId());
        stockOption.setStockCode(stStock.getCode());
        stockOption.setStockName(stStock.getName());
        stockOption.setStockGid(stStock.getVarieties());
        stockOption.setStockGid(stStock.getMarket());
        stockOption.setIsLock(0);
        stockOption.setAddTime(new Date());

        int insertCount = this.stockOptionMapper.insert(stockOption);
        if (insertCount > 0) {
            return ServerResponse.createBySuccessMsg("Added Self-Selected Stock Successfully");
        }
        return ServerResponse.createByErrorMsg("Failed to add, please try again");
    }


    public ServerResponse delOption(String stockCode, HttpServletRequest request) {
        User user = getCurrentUser(request);
        if (user == null) {
            return ServerResponse.createByErrorMsg("Please log in first.");
        }
//        String stockcode = code;
//        if (code.contains("hf")) {
//            stockcode = code.split("_")[1].toString();
//        }

//        QueryWrapper<StStock> stockQueryWrapper = new QueryWrapper<>();
//        stockQueryWrapper.eq("code", stockCode);
//        StStock stStock = stStockMapper.selectOne(stockQueryWrapper);
//
//        if (null == stStock) {
//            return ServerResponse.createByErrorMsg("Cancellation failed, stock does not exist");
//        }
        
        
//        stockcode = stockcode.replace("sh", "").replace("sz", "").replace("bj", "");
        StockOption stockOption = this.stockOptionMapper.findMyOptionIsExistByCode(user.getId(), stockCode);
        if (stockOption == null) {
            return ServerResponse.createByErrorMsg("Failure to cancel, self-selected shares do not exist");
        }

        int delCount = this.stockOptionMapper.deleteByPrimaryKey(stockOption.getId());
        if (delCount > 0) {
            return ServerResponse.createBySuccessMsg("Successful cancellation of self-selected shares");
        }
        return ServerResponse.createByErrorMsg("Cancellation failed, please try again.");
    }


    public ServerResponse isOption(String stockCode, String market, HttpServletRequest request) {

        if(StringUtils.isBlank(stockCode)){
            return ServerResponse.createByErrorMsg("The stock code is empty.");
        }

        User user = getCurrentUser(request);

        if (user == null) {
            return ServerResponse.createByErrorMsg("Please log in first.");
        }
//        String stockcode = code;
//        if (code.contains("hf")) {
//            stockcode = code.split("_")[1].toString();
//        }
//        stockcode = stockcode.replace("sh", "").replace("sz", "").replace("bj", "");
        QueryWrapper<StStock> stockQueryWrapper = new QueryWrapper<>();
        stockQueryWrapper.eq("code", stockCode);
        stockQueryWrapper.eq("market", market);
        StStock stStock = stStockMapper.selectOne(stockQueryWrapper);
        if (null == stStock) {
            return ServerResponse.createByErrorMsg("The inquiry failed, and the stock does not exist.");
        }
        return this.iStockOptionService.isOption(user.getId(), stockCode);
    }

    public ServerResponse getUserInfo(HttpServletRequest request) {

        User user = iUserService.getCurrentRefreshUser(request);
        if (user == null) {
            return ServerResponse.createByErrorMsg("Please log in first.");
        }

        // 计算总盈亏 和 冻结资金
        UserInfoVO userInfoVO = assembleUserInfoVO(user);
        // 获取银行卡信息
        UserBank userBank = this.iUserBankService.findUserBankByUserId(user.getId());
        userInfoVO.setBank(userBank);
        // 获取 usdt 信息
        UserUsdt userUsdt = this.userUsdtService.findUserUsdtByUserId(user.getId());
        userInfoVO.setUsdt(userUsdt);

        // 如果用户已实名通过，则不返回证件信息
        Integer isActive = userInfoVO.getIsActive();
        if (User.IS_ACTIVE_SUCCESS.equals(isActive)) {
            userInfoVO.setImg1Key("");
            userInfoVO.setImg2Key("");
        }
        return ServerResponse.createBySuccess(userInfoVO);
    }


    public ServerResponse updatePwd(String oldPwd, String newPwd, HttpServletRequest request) {
        if (StringUtils.isBlank(oldPwd) || StringUtils.isBlank(newPwd)) {
            return ServerResponse.createByErrorMsg("Parameters cannot be empty.");
        }

        User user = getCurrentRefreshUser(request);
        if (user == null) {
            return ServerResponse.createByErrorMsg("Please log in first.");
        }
        oldPwd = SymmetricCryptoUtil.encryptPassword(oldPwd);
        if (!oldPwd.equals(user.getUserPwd())) {
            return ServerResponse.createByErrorMsg("Wrong password");
        }

        user.setUserPwd(SymmetricCryptoUtil.encryptPassword(newPwd));
        int updateCount = this.userMapper.updateByPrimaryKeySelective(user);
        if (updateCount > 0) {
            return ServerResponse.createBySuccessMsg("Successful modification");
        }
        return ServerResponse.createByErrorMsg("Modification Failed");
    }


    /**
     * 修改用户信息
     * @param phone
     * @param email
     * @param nickName
     * @param headImg
     * @param request
     * @return
     */
    @Override
    public ServerResponse updateUserInfo(String code, String phone, String email, String nickName, String headImg, HttpServletRequest request) {
        User user = getCurrentRefreshUser(request);
        if (user == null) {
            return ServerResponse.createByErrorMsg("Please log in first.");
        }
        if (StringUtils.isNotBlank(phone) && !phone.equals(user.getPhone())) {
            User info = this.userMapper.findByPhoneOrEmail(phone);
            if (info != null) {
                return ServerResponse.createByErrorMsg("The mobile phone number already exists.");
            }
        }
        if (StringUtils.isNotBlank(email) && !email.equals(user.getEmail())) {
            User info = this.userMapper.findByPhoneOrEmail(email);
            if (info != null) {
                return ServerResponse.createByErrorMsg("The mailbox already exists.");
            }
        }
        user.setCode(code);
        user.setPhone(phone);
        user.setEmail(email);
        user.setNickName(nickName);
        user.setImg3Key(headImg);
        userMapper.updateByPrimaryKeySelective(user);
        return ServerResponse.createBySuccessMsg("Successful modification");
    }


    public ServerResponse updatePwd(String type, String code, String account, String newPwd) {
        if (StringUtils.isBlank(type) || StringUtils.isBlank(account) || StringUtils.isBlank(newPwd)) {
            return ServerResponse.createByErrorMsg("Parameters cannot be empty.");
        }

        User user = new User();
        if (LoginType.PHONE.getCode().equals(type)) {
            if (StringUtils.isBlank(code)) {
                return ServerResponse.createByErrorMsg("phone area code cannot be empty.");
            }
            user = this.userMapper.findByPhone(code, account);
        } else {
            user = this.userMapper.findByPhoneOrEmail(account);
        }

        if (user == null) {
            return ServerResponse.createByErrorMsg("User does not exist");
        }

        user.setUserPwd(SymmetricCryptoUtil.encryptPassword(newPwd));
        int updateCount = this.userMapper.updateByPrimaryKeySelective(user);
        if (updateCount > 0) {
            return ServerResponse.createBySuccess("Successfully changed the password！");
        }
        return ServerResponse.createByErrorMsg("Failed to change the password!");
    }

    /**
     * 设置支付密码
     * @param request
     * @param payPwd
     * @return
     */
    @Override
    public ServerResponse setPayPwd(HttpServletRequest request, String payPwd) {
        User user = getCurrentRefreshUser(request);
        if (user == null) {
            return ServerResponse.createByErrorMsg("Please log in first.");
        }

        user.setIsPayPwd(User.SET_PAY_PWD_YES);
        user.setPayPwd(SymmetricCryptoUtil.encryptPassword(payPwd));
        userMapper.updateByPrimaryKeySelective(user);
        return ServerResponse.createBySuccess();
    }

    /**
     * 校验支付密码
     * @param request
     * @param currPayPwd
     * @return
     */
    @Override
    public ServerResponse checkPayPwd(HttpServletRequest request, String currPayPwd) {
        User user = getCurrentRefreshUser(request);
        if (user == null) {
            return ServerResponse.createByErrorMsg("Please log in first.");
        }
        String payPwd = user.getPayPwd();
        // 校验当前密码来验证身份
        if (!SymmetricCryptoUtil.encryptPassword(currPayPwd).equals(payPwd)) {
            return ServerResponse.createByErrorMsg("The original password is incorrect.");
        }
        return ServerResponse.createBySuccess();
    }

    public ServerResponse update(User user) {

        log.info("#####修改用户信息 UserId = {}, 用户配资资金 = {} 可用资金 = {}", user.getId(), user.getTradingAmount(), user.getEnableAmt());
        if (user.getAgentId() != null) {
            AgentUser agentUser = this.agentUserMapper.selectByPrimaryKey(user.getAgentId());
            if (agentUser != null) {
                user.setAgentName(agentUser.getAgentName());
            }
        }


        String pwd = user.getUserPwd();
        if (StrUtil.isNotBlank(pwd)) {
            user.setUserPwd(SymmetricCryptoUtil.encryptPassword(pwd));
        }

        String payPwd = user.getPayPwd();
        if (StringUtils.isNotBlank(payPwd)) {
            user.setPayPwd(SymmetricCryptoUtil.encryptPassword(payPwd));
        }

        Integer parentId = user.getParentId();
        if (null == parentId) {
            user.setParentId(0);
        }

        int updateCount = this.userMapper.updateByPrimaryKeySelective(user);
        if (updateCount > 0) {
            return ServerResponse.createBySuccessMsg("Successful modification");
        }
        return ServerResponse.createByErrorMsg("Modification Failed");
    }


    public ServerResponse auth(String realName, String idCard, String img1key, String img2key, String img3key, HttpServletRequest request) {
        if (StringUtils.isBlank(realName) ||
                StringUtils.isBlank(idCard) ||
                StringUtils.isBlank(img1key) ||
                StringUtils.isBlank(img2key)) {

            return ServerResponse.createByErrorMsg("Parameters cannot be empty.");
        }

        User user = getCurrentRefreshUser(request);
        if (user == null) {
            return ServerResponse.createByErrorMsg("Please log in first.！");
        }

        if (((0 != user.getIsActive().intValue())) & ((3 != user.getIsActive().intValue()))) {
            return ServerResponse.createByErrorMsg("Current status cannot be authenticated.");
        }

        User idCardUser = userMapper.selectByIdCard(idCard);
        if (null != idCardUser) {
            Integer isActive = idCardUser.getIsActive();
            if (isActive == 2) {
                return ServerResponse.createByErrorMsg("The identity information has been submitted to the audit, if in doubt, please contact customer service!");
            }
        }

        user.setNickName(realName);
        user.setRealName(realName);
        user.setIdCard(idCard);

        user.setImg1Key(img1key);
        user.setImg2Key(img2key);
        user.setImg3Key(img3key);
        user.setIsActive(Integer.valueOf(1));
        log.info("##### 用户认证 ####, 可用资金 = {}", user.getEnableAmt());

        int updateCount = this.userMapper.updateByPrimaryKeySelective(user);
        if (updateCount > 0) {
            return ServerResponse.createBySuccessMsg("In real-name authentication");
        }
        return ServerResponse.createByErrorMsg("Real-name authentication failed");
    }


    public ServerResponse transAmt(Integer amt, Integer type, HttpServletRequest request) {
        User user = getCurrentRefreshUser(request);
        if (user == null) {
            return ServerResponse.createByErrorMsg("Please log in first.");
        }
        if (amt.intValue() <= 0) {
            return ServerResponse.createByErrorMsg("The amount is incorrect.");
        }


        if (1 == type.intValue()) {
            if (user.getEnableAmt().compareTo(new BigDecimal(amt)) == -1) {
                return ServerResponse.createByErrorMsg("Insufficient funds available in financing accounts");
            }

            BigDecimal userAmt = user.getUserAmt().subtract(new BigDecimal(amt));
            BigDecimal enableAmt = user.getEnableAmt().subtract(new BigDecimal(amt));
            BigDecimal userIndexAmt = user.getUserIndexAmt().add(new BigDecimal(amt));
            BigDecimal enableIndexAmt = user.getEnableIndexAmt().add(new BigDecimal(amt));

//            user.setUserAmt(userAmt);
            user.setEnableAmt(enableAmt);
            user.setUserIndexAmt(userIndexAmt);
            user.setEnableIndexAmt(enableIndexAmt);
            int updateCount = this.userMapper.updateByPrimaryKeySelective(user);
            if (updateCount > 0) {
                saveAmtTransLog(user, type, amt);
                return ServerResponse.createBySuccessMsg("Successful transfer");
            }
            return ServerResponse.createByErrorMsg("Transfer Failed");
        }


        if (2 == type.intValue()) {

            /**
             * 有持仓时，指数账户不能转到账户余额
             */
            List<UserPosition> userPositions = this.iUserPositionService.findPositionByUserIdAndSellIdIsNull(user.getId());
            if (userPositions.size() > 0) {
                return ServerResponse.createByErrorMsg("If there is a position, it cannot be transferred.");
            }


            if (user.getEnableIndexAmt().compareTo(new BigDecimal(amt.intValue())) == -1) {
                return ServerResponse.createByErrorMsg("Insufficient funds available in index accounts");
            }

            BigDecimal userAmt = user.getUserAmt().add(new BigDecimal(amt.intValue()));
            BigDecimal enableAmt = user.getEnableAmt().add(new BigDecimal(amt.intValue()));
            BigDecimal userIndexAmt = user.getUserIndexAmt().subtract(new BigDecimal(amt.intValue()));
            BigDecimal enableIndexAmt = user.getEnableIndexAmt().subtract(new BigDecimal(amt.intValue()));

//            user.setUserAmt(userAmt);
            user.setEnableAmt(enableAmt);
            user.setUserIndexAmt(userIndexAmt);
            user.setEnableIndexAmt(enableIndexAmt);
            int updateCount = this.userMapper.updateByPrimaryKeySelective(user);
            if (updateCount > 0) {
                saveAmtTransLog(user, type, amt);
                return ServerResponse.createBySuccessMsg("Successful transfer");
            }
            return ServerResponse.createByErrorMsg("Failed to transfer");
        }


        if (3 == type.intValue()) {
            if (user.getEnableAmt().compareTo(new BigDecimal(amt.intValue())) == -1) {
                return ServerResponse.createByErrorMsg("Insufficient funds available in the index account");
            }

            BigDecimal userAmt = user.getUserAmt().subtract(new BigDecimal(amt.intValue()));
            BigDecimal enableAmt = user.getEnableAmt().subtract(new BigDecimal(amt.intValue()));
            BigDecimal userFutAmt = user.getUserFutAmt().add(new BigDecimal(amt.intValue()));
            BigDecimal enableFutAmt = user.getEnableFutAmt().add(new BigDecimal(amt.intValue()));

//            user.setUserAmt(userAmt);
            user.setEnableAmt(enableAmt);
            user.setUserFutAmt(userFutAmt);
            user.setEnableFutAmt(enableFutAmt);
            int updateCount = this.userMapper.updateByPrimaryKeySelective(user);
            if (updateCount > 0) {
                saveAmtTransLog(user, type, amt);
                return ServerResponse.createBySuccessMsg("Successful transfer");
            }
            return ServerResponse.createByErrorMsg("Failed to transfer");
        }


        if (4 == type.intValue()) {
            if (user.getEnableFutAmt().compareTo(new BigDecimal(amt.intValue())) == -1) {
                return ServerResponse.createByErrorMsg("Insufficient funds available in futures accounts");
            }

            BigDecimal userAmt = user.getUserAmt().add(new BigDecimal(amt.intValue()));
            BigDecimal enableAmt = user.getEnableAmt().add(new BigDecimal(amt.intValue()));
            BigDecimal userFutAmt = user.getUserFutAmt().subtract(new BigDecimal(amt.intValue()));
            BigDecimal enableFutAmt = user.getEnableFutAmt().subtract(new BigDecimal(amt.intValue()));

//            user.setUserAmt(userAmt);
            user.setEnableAmt(enableAmt);
            user.setUserFutAmt(userFutAmt);
            user.setEnableFutAmt(enableFutAmt);

            int updateCount = this.userMapper.updateByPrimaryKeySelective(user);
            if (updateCount > 0) {
                saveAmtTransLog(user, type, amt);
                return ServerResponse.createBySuccessMsg("Successful transfer");
            }
            return ServerResponse.createByErrorMsg("Failed to transfer");
        }


        return ServerResponse.createByErrorMsg("Type error");
    }


    private void saveAmtTransLog(User user, Integer type, Integer amt) {
        String amtFrom = "";
        String amtTo = "";
        if (1 == type.intValue()) {
            amtFrom = "融资";
            amtTo = "指数";
        } else if (2 == type.intValue()) {
            amtFrom = "指数";
            amtTo = "融资";
        } else if (3 == type.intValue()) {
            amtFrom = "融资";
            amtTo = "期货";
        } else if (4 == type.intValue()) {
            amtFrom = "期货";
            amtTo = "融资";
        }

        SiteAmtTransLog siteAmtTransLog = new SiteAmtTransLog();
        siteAmtTransLog.setUserId(user.getId());
        siteAmtTransLog.setRealName(user.getRealName());
        siteAmtTransLog.setAgentId(user.getAgentId());
        siteAmtTransLog.setAmtFrom(amtFrom);
        siteAmtTransLog.setAmtTo(amtTo);
        siteAmtTransLog.setTransAmt(new BigDecimal(amt.intValue()));
        siteAmtTransLog.setAddTime(new Date());
        this.siteAmtTransLogMapper.insert(siteAmtTransLog);
    }


    /**
     * 强制平仓任务
     */
    public void ForceSellTask() {
        List<Integer> userIdList = this.iUserPositionService.findDistinctUserIdList();
        log.info("当前有持仓单的用户数量 为 {}", Integer.valueOf(userIdList.size()));

        for (int i = 0; i < userIdList.size(); i++) {
            log.info("=========开始执行平仓操作============");
            Integer userId = (Integer) userIdList.get(i);
            User user = this.userMapper.selectByPrimaryKey(userId);
            if (user == null) {
                continue;
            }
            // 处理平仓
            handleClosePosition(user);

        }
    }

    public void handleClosePosition(User user){
        // 查询所有股票持仓记录
        List<UserPosition> userPositions = this.iUserPositionService.findPositionByUserIdAndSellIdIsNull(user.getId());
        log.info("用户id = {} 姓名 = {} 持仓中订单数： {}", new Object[]{user.getId(), user.getRealName(), Integer.valueOf(userPositions.size())});

        // 平仓逻辑：当用户没有配资时，无需强制平仓，有配资时，跌幅不能超过配资资金（也就是跌的钱不能用配资资金补充）
        List<FundsApply> fundsApplyList = fundsApplyMapper.getUserEnabledSubaccount(user.getId());

        if (CollUtil.isNotEmpty(fundsApplyList)) {
            // 用户配资总金额
            BigDecimal totalAllocationAmount = new BigDecimal(BigInteger.ZERO);
            for (FundsApply apply : fundsApplyList) {
                BigDecimal fundsAmount = apply.getFundsAmount();
                totalAllocationAmount = totalAllocationAmount.add(fundsAmount);
            }

            // 当前用户持仓股票的总市值
            BigDecimal totalNowPrice = new BigDecimal(BigInteger.ZERO);

            // 查询用户当前持仓股票的总市值
            for(UserPosition position : userPositions){
                // 交易所
                String stockSpell = position.getStockSpell();
                // 股票代码
                String stockCode = position.getStockCode();
                // 实时查询最新价格
                StStockTickerDetails tickerDetails = stocksComponent.queryDetailsByMarketAndCode(stockSpell, stockCode);

                // stocksComponent.thirdInterfaceStatistic(StocksComponent.MINI_PRICES, "handleClosePosition");

                BigDecimal nowPrice = new BigDecimal("0.00");
                if (null != tickerDetails) {
                    StockTickerListInfo data = tickerDetails.getData();
                    if(null != data) {
                        nowPrice = data.getPrice();
                    }
                }

                // 计算当前持有的股票的总市值
                Integer orderNum = position.getOrderNum();
                // 计算出当前市值
                BigDecimal stockMarket = nowPrice.multiply(new BigDecimal(orderNum));
                totalNowPrice = totalNowPrice.add(stockMarket);
            }

            // 计算用户使用了多少配资金额用于购买股票或者基金（这里购买基金也用配资的钱了）

            // 当前用户剩余的配资资金
            BigDecimal tradingAmount = user.getTradingAmount();
            // 已使用的配资资金
            BigDecimal usedTradingAmount = totalAllocationAmount.subtract(tradingAmount);
            // 用户可用现金
            BigDecimal userEnableAmt = user.getEnableAmt();
            // 当用户的可用金额小于已使用的配资资金时，说明用户没有还款能力，需要强制平仓
            if (userEnableAmt.compareTo(usedTradingAmount) < 0) {
                // 如果小于已使用的配资资金时，需要考虑平仓来填补配资金额了

                // 看一下目前股票的总市值是否达到平仓比例，计算公式：（股票目前的总市值+可用资金） * 设置的比例 <= 已使用的配资资金时进行平仓，并且需要将配资账户补充全
                // 例如：当前已使用的配资资金是1W， 设置的比例是0.8， 那么当前市值加上可用资金就得是 1.3W左右，

                SiteSetting siteSetting = this.iSiteSettingService.getSiteSetting();
                BigDecimal force_stop_percent = siteSetting.getForceStopPercent();

                // 股票目前的总市值+可用资金
                BigDecimal userOwnedAmount = totalNowPrice.add(userEnableAmt);
                // 平仓比例后的用户资金
                BigDecimal closingRatio = userOwnedAmount.multiply(force_stop_percent);

                if (closingRatio.compareTo(usedTradingAmount) <= 0){
                    // 执行平仓逻辑
                    for(UserPosition position : userPositions){
                        log.info("强制平仓该用户所有的持仓单，userId = {} 订单号 = {}", user.getId(), position.getPositionSn());
                        try {
                            // 当天买入的股票不执行平仓逻辑
                            if (!DateTimeUtil.sameDate(DateTimeUtil.getCurrentDate(), position.getBuyOrderTime())) {
                                String payPwd = user.getPayPwd();
                                String decryptPassword = SymmetricCryptoUtil.decryptPassword(payPwd);
                                this.iUserPositionService.sellNew(position.getPositionSn(), position.getStockSpell(), position.getOrderNum(), decryptPassword, user.getId());
                            }
                        } catch (Exception e) {
                            log.error("[盈亏达到最大亏损]强制平仓失败...");
                        }
                    }

                    SiteTaskLog siteTaskLog = new SiteTaskLog();
                    siteTaskLog.setTaskType("Forced liquidation");
                    String accountType = (user.getAccountType().intValue() == 0) ? "Official user" : "Impersonate the user";
                    String taskcnt = accountType + "-" + user.getRealName() + "Strongly flat [two financing profits and losses reach the maximum loss] userid = " + user.getId() + ", enable_user_amt = " + userEnableAmt + "userOwnedAmount = " + userOwnedAmount + ", force_stop_percent = " + force_stop_percent + ", closingRatio=" + closingRatio;
                    siteTaskLog.setTaskCnt(taskcnt);
                    String tasktarget = "This time, I strongly flattened " + userPositions.size() + " stock holding orders. order number:" + userPositions.size();
                    siteTaskLog.setTaskTarget(tasktarget);
                    siteTaskLog.setAddTime(new Date());
                    siteTaskLog.setIsSuccess(Integer.valueOf(0));
                    siteTaskLog.setErrorMsg("");
                    int insertTaskCount = this.siteTaskLogMapper.insert(siteTaskLog);
                    if (insertTaskCount > 0) {
                        log.info("[盈亏达到最大亏损]保存强制平仓task任务成功");
                    } else {
                        log.info("[盈亏达到最大亏损]保存强制平仓task任务失败");
                    }

                } else {
                    log.info("用户未达到强制平仓线，不做强平处理...");
                }
                log.info("=======平仓结束==============");
            }
        }


    }

    /**
     * 用户持仓单-单支股票盈亏-强平定时
     */
    public void ForceSellOneStockTask() {
        List<Integer> userIdList = this.iUserPositionService.findDistinctUserIdList();
        log.info("当前有持仓单的用户数量 为 {}", Integer.valueOf(userIdList.size()));

        SiteSetting siteSetting = this.iSiteSettingService.getSiteSetting();
        // 强制停止百分比
        BigDecimal force_stop_percent = siteSetting.getForceStopPercent();
        for (int i = 0; i < userIdList.size(); i++) {
            log.info("=========单只股票强制平仓开始============");
            Integer userId = (Integer) userIdList.get(i);
            User user = this.userMapper.selectByPrimaryKey(userId);
            if (user == null) {
                continue;
            }

            List<UserPosition> userPositions = this.iUserPositionService.findPositionByUserIdAndSellIdIsNull(userId);
            log.info("用户id = {} 姓名 = {} 持仓中订单数： {}", new Object[]{userId, user.getRealName(), Integer.valueOf(userPositions.size())});

            BigDecimal enable_user_amt = user.getEnableAmt();
            BigDecimal all_freez_amt = new BigDecimal("0");
            for (UserPosition position : userPositions) {
                PositionProfitVO positionProfitVO = iUserPositionService.getPositionProfitVO(position);
                if(null == positionProfitVO){
                    continue;
                }
                //(沪深)单支股票强制平仓线 = (下单总金额 / 杠杆 + 追加保证金) *  0.8
                BigDecimal user_force_amt = position.getOrderTotalPrice().divide(new BigDecimal(position.getOrderLever())).add(position.getMarginAdd()).multiply(force_stop_percent);
                BigDecimal fu_user_force_amt = user_force_amt.negate(); //负平仓线
                log.info("用户强制平仓线金额 = {}", user_force_amt);
                /*if("1601344387923698".equals( position.getPositionSn())){
                    log.info("test = {}", position.getPositionSn());
                }*/


                boolean isProfit = false;
                //总盈亏<=0  并且  强制负平仓线>=总盈亏
                isProfit = (positionProfitVO.getAllProfitAndLose().compareTo(new BigDecimal("0")) < 1 && fu_user_force_amt.compareTo(positionProfitVO.getAllProfitAndLose()) > -1);
                if (isProfit && !DateTimeUtil.sameDate(DateTimeUtil.getCurrentDate(), position.getBuyOrderTime())) {
                    try {
                        String payPwd = user.getPayPwd();
                        String decryptPassword = SymmetricCryptoUtil.decryptPassword(payPwd);
                        this.iUserPositionService.sellNew(position.getPositionSn(), position.getStockSpell(), position.getOrderNum(), decryptPassword, userId);

                        SiteTaskLog siteTaskLog = new SiteTaskLog();
                        siteTaskLog.setTaskType("Single-stock leveling task - stock holdings");
                        String accountType = (user.getAccountType().intValue() == 0) ? "Official user" : "Impersonate the user";
                        String taskcnt = accountType + "-" + user.getRealName() + "Strongly flat [two financing profits and losses reach the maximum loss] userid = " + user.getId() + ", enable_user_amt = " + enable_user_amt + "all_freez_amt = " + all_freez_amt + ", force_stop_percent = " + force_stop_percent + ", AllProfitAndLose" + positionProfitVO.getAllProfitAndLose() + ", user_force_amt:" + user_force_amt;
                        siteTaskLog.setTaskCnt(taskcnt);
                        String tasktarget = "This Qiangping order number：" + position.getPositionSn();
                        siteTaskLog.setTaskTarget(tasktarget);
                        siteTaskLog.setAddTime(new Date());
                        siteTaskLog.setIsSuccess(Integer.valueOf(0));
                        siteTaskLog.setErrorMsg("");
                        int insertTaskCount = this.siteTaskLogMapper.insert(siteTaskLog);
                        if (insertTaskCount > 0) {
                            log.info("[盈亏达到最大亏损]保存强制平仓task任务成功");
                        } else {
                            log.info("[盈亏达到最大亏损]保存强制平仓task任务失败");
                        }
                    } catch (Exception e) {
                        log.error("[盈亏达到最大亏损]强制平仓失败...");
                    }
                }

            }
            log.info("=====================");
        }
    }

    /*用户持仓单-单支股票/止损止盈-强平定时*/
    public void ForceSellOneStockTaskV2() {
        List<Integer> userIdList = this.iUserPositionService.findDistinctUserIdList();
        log.info("当前有持仓单的用户数量 为 {}", Integer.valueOf(userIdList.size()));
        SiteSetting siteSetting = this.iSiteSettingService.getSiteSetting();
        BigDecimal force_stop_percent = siteSetting.getForceStopPercent();
        for (int i = 0; i < userIdList.size(); i++) {
            log.info("=====================");
            Integer userId = (Integer) userIdList.get(i);
            User user = this.userMapper.selectByPrimaryKey(userId);
            if (user == null) {
                continue;
            }
            List<UserPosition> userPositions = this.iUserPositionService.findPositionByUserIdAndSellIdIsNull(userId);
            log.info("用户id = {} 姓名 = {} 持仓中订单数： {}", new Object[]{userId, user.getRealName(), Integer.valueOf(userPositions.size())});

            BigDecimal enable_user_amt = user.getEnableAmt();
            BigDecimal all_freez_amt = new BigDecimal("0");
            for (UserPosition position : userPositions) {
//                PositionProfitVO positionProfitVO = iUserPositionService.getPositionProfitVO(position);
//                if (positionProfitVO == null) {
//                    continue;
//                }

//                StockListVO stockListVO = new StockListVO();
//                if (position.getStockGid().contains("hk")) {
//                    String hk = RedisShardedPoolUtils.get(position.getStockGid(), 1);
//
//                    stockListVO = SinaStockApi.otherStockListVO(hk);
//                } else if (position.getStockGid().contains("us")) {
//                    String us = RedisShardedPoolUtils.get(position.getStockGid(), 2);
//                    stockListVO = SinaStockApi.otherStockListVO(us);
//                } else {
//                    stockListVO = SinaStockApi.assembleStockListVO(SinaStockApi.getSinaStock(position.getStockGid()));
//                }
//                if (stockListVO == null) {
//                    continue;
//                }
                // 使用新版股票数据
                String stockCode = position.getStockCode();
                String market = position.getStockSpell();
                QueryWrapper<StStock> stockQueryWrapper = new QueryWrapper<>();
                stockQueryWrapper.eq("code", stockCode);
                stockQueryWrapper.eq("market", market);
                StStock stStock = stStockMapper.selectOne(stockQueryWrapper);
                if (null == stStock) {
                    log.info("下单失败，股票不存在！");
                }
//                String market = stStock.getMarket();

                // 查询该股票的实时价格
                StStockTickerDetails tickerDetails = stocksComponent.queryDetailsByMarketAndCode(market, stockCode);

                // stocksComponent.thirdInterfaceStatistic(StocksComponent.MINI_PRICES, "ForceSellOneStockTaskV2");

                if (null == tickerDetails) {
                    log.info("查询股票实时价格失败！【tickerDetails】");
                }

                StockTickerListInfo tickerInfo = tickerDetails.getData();
                if (null == tickerInfo) {
                    log.info("查询股票实时价格失败！【tickerInfo】");
                }

                BigDecimal nowPrice = tickerInfo.getPrice();
                Boolean isSell = Boolean.valueOf(false);
                if (position.getOrderDirection().equals("Buy Up")) {
                    if (position.getProfitTargetPrice() != null
                            && position.getProfitTargetPrice().compareTo(nowPrice) <= 0) {
                        isSell = Boolean.valueOf(true);
                    }
                    if (position.getStopTargetPrice() != null
                            && position.getStopTargetPrice().compareTo(nowPrice) >= 0) {
                        isSell = Boolean.valueOf(true);
                    }
                } else if (position.getOrderDirection().equals("Buy down")) {
                    if (position.getProfitTargetPrice() != null
                            && position.getProfitTargetPrice().compareTo(nowPrice) >= 0) {
                        isSell = Boolean.valueOf(true);
                    }
                    if (position.getStopTargetPrice() != null
                            && position.getStopTargetPrice().compareTo(nowPrice) <= 0) {
                        isSell = Boolean.valueOf(true);
                    }

                }

                if (isSell) {

                    try {
                        this.iUserPositionService.sell(position.getPositionSn(), 0);
                        SiteTaskLog siteTaskLog = new SiteTaskLog();
                        siteTaskLog.setTaskType("Single share take profit stop loss strong leveling task - stock position");
                        String accountType = (user.getAccountType().intValue() == 0) ? "Official user" : "Impersonate the user";
                        String taskcnt = accountType + "-" + user.getRealName() + "Strongly flat [achieved the target profit and loss] userid = " + user.getId() + ", enable_user_amt = " + enable_user_amt + "all_freez_amt = " + all_freez_amt + ", force_stop_percent = " + force_stop_percent + ",nowPrice" + nowPrice + ", ProfitTargetPrice:" + position.getProfitTargetPrice() + ", StopTargetPrice:" + position.getStopTargetPrice();
                        siteTaskLog.setTaskCnt(taskcnt);
                        String tasktarget = "The order number of Qiangping is：" + position.getPositionSn();
                        siteTaskLog.setTaskTarget(tasktarget);
                        siteTaskLog.setAddTime(new Date());
                        siteTaskLog.setIsSuccess(Integer.valueOf(0));
                        siteTaskLog.setErrorMsg("");
                        int insertTaskCount = this.siteTaskLogMapper.insert(siteTaskLog);
                        if (insertTaskCount > 0) {
                            log.info("[盈利达到目标盈利]保存强制平仓task任务成功");
                        } else {
                            log.info("[盈利达到目标盈利]保存强制平仓task任务失败");
                        }
                    } catch (Exception e) {
                        log.error("[盈利达到目标盈利]强制平仓失败...");
                    }

                }

            }
            log.info("=========止盈止损定时任务============");
        }
    }

    /*用户股票持仓单-强平提醒推送消息定时*/
    public void ForceSellMessageTask() {
        List<Integer> userIdList = this.iUserPositionService.findDistinctUserIdList();

        log.info("当前有持仓单的用户数量 为 {}", Integer.valueOf(userIdList.size()));

        for (int i = 0; i < userIdList.size(); i++) {
            log.info("=====================");
            Integer userId = (Integer) userIdList.get(i);
            User user = this.userMapper.selectByPrimaryKey(userId);
            if (user == null) {
                continue;
            }


            List<UserPosition> userPositions = this.iUserPositionService.findPositionByUserIdAndSellIdIsNull(userId);

            log.info("用户id = {} 姓名 = {} 持仓中订单数： {}", new Object[]{userId, user.getRealName(), Integer.valueOf(userPositions.size())});


            BigDecimal enable_user_amt = user.getEnableAmt();

//            for (UserPosition position : userPositions) {
//
//                BigDecimal actual_amt = position.getOrderTotalPrice().divide(new BigDecimal(position
//                        .getOrderLever().intValue()), 2, 4);
//
//
//                all_freez_amt = all_freez_amt.add(actual_amt);
//            }
            // 总冻结金额
            BigDecimal all_freez_amt = new BigDecimal("0");
            // 总盈亏
            BigDecimal all_profit_and_lose = new BigDecimal("0");
            PositionVO positionVO = this.iUserPositionService.findUserPositionAllProfitAndLose(userId);
            all_profit_and_lose = positionVO.getAllProfitAndLose();
            all_freez_amt = positionVO.getAllFreezAmt();

            SiteSetting siteSetting = this.iSiteSettingService.getSiteSetting();
            BigDecimal force_stop_percent = siteSetting.getForceStopRemindRatio();
            /*BigDecimal force_stop_amt = force_stop_percent.multiply(all_freez_amt);
            BigDecimal user_force_amt = enable_user_amt.add(force_stop_amt);
            boolean isProfit = false;
            isProfit = (all_profit_and_lose.compareTo(new BigDecimal("0")) == -1 && user_force_amt.compareTo(all_profit_and_lose.negate()) != 1);
            */
            BigDecimal force_stop_amt = enable_user_amt.add(all_freez_amt);

            //(沪深)强制平仓线 = (账户可用资金 + 冻结保证金) *  0.8
            BigDecimal user_force_amt = force_stop_percent.multiply(force_stop_amt);
            BigDecimal fu_user_force_amt = user_force_amt.negate(); //负平仓线
            log.info("用户强制平仓线金额 = {}", user_force_amt);
            boolean isProfit = false;

            //总盈亏<=0  并且  强制负平仓线>=总盈亏
            isProfit = (all_profit_and_lose.compareTo(new BigDecimal("0")) < 1 && fu_user_force_amt.compareTo(all_profit_and_lose) > -1);
            if (isProfit) {
                log.info("强制平仓该用户所有的持仓单");
                int count = iSiteMessageService.getIsDayCount(userId, "Stock alerts");
                if (count == 0) {
                    //给达到消息强平提醒用户推送消息
                    SiteMessage siteMessage = new SiteMessage();
                    siteMessage.setUserId(userId);
                    siteMessage.setUserName(user.getRealName());
                    siteMessage.setTypeName("Stock alerts");
                    siteMessage.setStatus(1);
                    siteMessage.setContent("【Stock alerts】o remind you, user id =”+ user.getId () +”, available funds =”+ enable +” frozen margin =”+ all +”, qiangping ratio =”+ Force +”, total profit and loss”+ all +”, reminder line:”+ user +”, please pay attention in time.");
                    siteMessage.setAddTime(DateTimeUtil.getCurrentDate());
                    iSiteMessageService.insert(siteMessage);
                }

            } else {
                log.info("用户未达到强制平仓线，不做强平处理...");
            }

            log.info("=====================");
        }
    }


    public void ForceSellIndexTask() {
        List<Integer> userIdList = this.iUserIndexPositionService.findDistinctUserIdList();

        log.info("当前有 指数持仓 的用户数量 为 {}", Integer.valueOf(userIdList.size()));

        for (int i = 0; i < userIdList.size(); i++) {
            log.info("=====================");
            Integer userId = (Integer) userIdList.get(i);
            User user = this.userMapper.selectByPrimaryKey(userId);
            if (user == null) {
                continue;
            }


            List<UserIndexPosition> userIndexPositions = this.iUserIndexPositionService.findIndexPositionByUserIdAndSellPriceIsNull(userId);

            log.info("用户id = {} 姓名 = {} 持仓中订单数: {}", new Object[]{userId, user
                    .getRealName(), Integer.valueOf(userIndexPositions.size())});


            IndexPositionVO indexPositionVO = this.iUserIndexPositionService.findUserIndexPositionAllProfitAndLose(userId);


            BigDecimal enable_index_amt = user.getEnableIndexAmt();


            BigDecimal all_freez_amt = indexPositionVO.getAllIndexFreezAmt();

            BigDecimal all_profit_and_lose = indexPositionVO.getAllIndexProfitAndLose();

            log.info("用户 {} 可用资金 = {} 总冻结保证金 = {} 所有持仓单的总盈亏 = {}", new Object[]{userId, enable_index_amt, all_freez_amt, all_profit_and_lose});


            SiteIndexSetting siteIndexSetting = this.iSiteIndexSettingService.getSiteIndexSetting();
            BigDecimal force_stop_percent = siteIndexSetting.getForceSellPercent();
            BigDecimal force_stop_amt = enable_index_amt.add(all_freez_amt);

            //(指数)强制平仓线 = (账户可用资金 + 冻结保证金) *  0.8
            BigDecimal user_force_amt = force_stop_percent.multiply(force_stop_amt);
            BigDecimal fu_user_force_amt = user_force_amt.negate(); //负平仓线
            log.info("用户强制平仓线金额 = {}", user_force_amt);
            boolean isProfit = false;
            //总盈亏<=0  并且  强制负平仓线>=总盈亏
            isProfit = (all_profit_and_lose.compareTo(new BigDecimal("0")) < 1 && fu_user_force_amt.compareTo(all_profit_and_lose) > -1);

            if (isProfit) {
                log.info("强制平仓该用户所有的指数持仓单");

                int[] arrs = new int[userIndexPositions.size()];
                for (int k = 0; k < userIndexPositions.size(); k++) {
                    UserIndexPosition userIndexPosition = (UserIndexPosition) userIndexPositions.get(k);
                    arrs[k] = userIndexPosition.getId().intValue();
                    try {
                        this.iUserIndexPositionService.sellIndex(userIndexPosition.getPositionSn(), 0);
                    } catch (Exception e) {
                        log.error("[盈亏达到最大亏损]强制平仓指数失败...");
                    }
                }


                SiteTaskLog siteTaskLog = new SiteTaskLog();
                siteTaskLog.setTaskType("强平任务-指数持仓");
                String accountType = (user.getAccountType().intValue() == 0) ? "Official user" : "Impersonate the user";
                String taskcnt = accountType + "-" + user.getRealName() + "被强平 [指数盈亏达到最大亏损] 用户 id = " + user.getId() + ", 可用资金 = " + enable_index_amt + ", 冻结资金 = " + all_freez_amt + ", 强平比例 = " + force_stop_percent + ", 总盈亏 = " + all_profit_and_lose + ", 强平线 = " + user_force_amt;


                siteTaskLog.setTaskCnt(taskcnt);

                String tasktarget = "此次强平" + userIndexPositions.size() + "条指数持仓订单, 订单号为" + Arrays.toString(arrs);
                siteTaskLog.setTaskTarget(tasktarget);
                siteTaskLog.setAddTime(new Date());
                siteTaskLog.setIsSuccess(Integer.valueOf(0));
                siteTaskLog.setErrorMsg("");
                int insertTaskCount = this.siteTaskLogMapper.insert(siteTaskLog);
                if (insertTaskCount > 0) {
                    log.info("[盈亏达到最大亏损] 保存强制平仓 指数 task任务成功");
                } else {
                    log.info("[盈亏达到最大亏损] 保存强制平仓 指数 task任务失败");
                }
            } else {
                log.info("用户指数持仓未达到强制平仓线, 不做强平处理...");
            }

            log.info("=====================");
        }
    }

    /*指数强平提醒推送消息，每分钟检测一次*/
    public void ForceSellIndexsMessageTask() {
        List<Integer> userIdList = this.iUserIndexPositionService.findDistinctUserIdList();

        log.info("当前有 指数持仓 的用户数量 为 {}", Integer.valueOf(userIdList.size()));

        for (int i = 0; i < userIdList.size(); i++) {
            log.info("=====================");
            Integer userId = (Integer) userIdList.get(i);
            User user = this.userMapper.selectByPrimaryKey(userId);
            if (user == null) {
                continue;
            }


            List<UserIndexPosition> userIndexPositions = this.iUserIndexPositionService.findIndexPositionByUserIdAndSellPriceIsNull(userId);

            log.info("用户id = {} 姓名 = {} 持仓中订单数: {}", new Object[]{userId, user
                    .getRealName(), Integer.valueOf(userIndexPositions.size())});


            IndexPositionVO indexPositionVO = this.iUserIndexPositionService.findUserIndexPositionAllProfitAndLose(userId);


            BigDecimal enable_index_amt = user.getEnableIndexAmt();


            BigDecimal all_freez_amt = indexPositionVO.getAllIndexFreezAmt();

            BigDecimal all_profit_and_lose = indexPositionVO.getAllIndexProfitAndLose();

            log.info("用户 {} 可用资金 = {} 总冻结保证金 = {} 所有持仓单的总盈亏 = {}", new Object[]{userId, enable_index_amt, all_freez_amt, all_profit_and_lose});


            SiteIndexSetting siteIndexSetting = this.iSiteIndexSettingService.getSiteIndexSetting();
            BigDecimal force_stop_percent = siteIndexSetting.getForceStopRemindRatio();
            BigDecimal force_stop_amt = enable_index_amt.add(all_freez_amt);

            //(指数)强制平仓线 = (账户可用资金 + 冻结保证金) *  0.8
            BigDecimal user_force_amt = force_stop_percent.multiply(force_stop_amt);
            BigDecimal fu_user_force_amt = user_force_amt.negate(); //负平仓线
            log.info("用户强制平仓线金额 = {}", user_force_amt);
            boolean isProfit = false;
            //总盈亏<=0  并且  强制负平仓线>=总盈亏
            isProfit = (all_profit_and_lose.compareTo(new BigDecimal("0")) < 1 && fu_user_force_amt.compareTo(all_profit_and_lose) > -1);

            if (isProfit) {
                log.info("强制平仓该用户所有的指数持仓单");

                int count = iSiteMessageService.getIsDayCount(userId, "指数预警");
                if (count == 0) {
                    //给达到消息强平提醒用户推送消息
                    SiteMessage siteMessage = new SiteMessage();
                    siteMessage.setUserId(userId);
                    siteMessage.setUserName(user.getRealName());
                    siteMessage.setTypeName("指数预警");
                    siteMessage.setStatus(1);
                    siteMessage.setContent("【指数预警】提醒您，用户id = " + user.getId() + ", 可用资金 = " + enable_index_amt + ", 冻结资金 = " + all_freez_amt + ", 强平比例 = " + force_stop_percent + ", 总盈亏 = " + all_profit_and_lose + ", 提醒线 = " + user_force_amt + "，请及时关注哦。");
                    siteMessage.setAddTime(DateTimeUtil.getCurrentDate());
                    iSiteMessageService.insert(siteMessage);
                }

            } else {
                log.info("用户指数持仓未达到强制平仓线, 不做强平处理...");
            }

            log.info("=====================");
        }
    }

    public void qh1() {
        this.stockPoll.qh1();
    }

    public void zs1() {
        this.stockPoll.zs1();
    }

    public void ForceSellFuturesTask() {
        List<Integer> userIdList = this.iUserFuturesPositionService.findDistinctUserIdList();


        for (int i = 0; i < userIdList.size(); i++) {
            log.info("===================== \n");
            Integer userId = (Integer) userIdList.get(i);
            System.out.println("userId" + userId);
            User user = this.userMapper.selectByPrimaryKey(userId);
            if (user == null) {
                continue;
            }

            List<UserFuturesPosition> userFuturesPositions = this.iUserFuturesPositionService.findFuturesPositionByUserIdAndSellPriceIsNull(userId);
            System.out.println("userFuturesPositions" + userFuturesPositions);
            System.out.println("继续");
            log.info("用户id = {} 姓名 = {} 期货持仓中订单数 {}", new Object[]{userId, user
                    .getRealName(), Integer.valueOf(userFuturesPositions.size())});

            FuturesPositionVO futuresPositionVO = this.iUserFuturesPositionService.findUserFuturesPositionAllProfitAndLose(userId);

            BigDecimal enable_Futures_amt = user.getEnableFutAmt();

            BigDecimal all_deposit_amt = futuresPositionVO.getAllFuturesDepositAmt();

            BigDecimal all_profit_and_lose = futuresPositionVO.getAllFuturesProfitAndLose();

            log.info("用户 {} 可用资金 = {} 总冻结保证金 = {} 所有持仓单的总盈亏 = {}", new Object[]{userId, enable_Futures_amt, all_deposit_amt, all_profit_and_lose});


            SiteFuturesSetting siteFuturesSetting = this.iSiteFuturesSettingService.getSetting();
            BigDecimal force_stop_percent = siteFuturesSetting.getForceSellPercent();
            BigDecimal force_stop_amt = enable_Futures_amt.add(all_deposit_amt);

            //(期货)强制平仓线 = (账户可用资金 + 冻结保证金) *  0.8
            BigDecimal user_force_amt = force_stop_percent.multiply(force_stop_amt);
            BigDecimal fu_user_force_amt = user_force_amt.negate(); //负平仓线
            log.info("用户强制平仓线金额 = {}", user_force_amt);

            boolean isProfit = false;

            //总盈亏<=0  并且  强制负平仓线>=总盈亏
            isProfit = (all_profit_and_lose.compareTo(new BigDecimal("0")) < 1 && fu_user_force_amt.compareTo(all_profit_and_lose) > -1);

            if (isProfit) {
                log.info("强制平仓用户 {} 所有的 期货 持仓单", user.getId());

                int[] arrs = new int[userFuturesPositions.size()];
                for (int k = 0; k < userFuturesPositions.size(); k++) {
                    UserFuturesPosition userFuturesPosition = (UserFuturesPosition) userFuturesPositions.get(k);
                    arrs[k] = userFuturesPosition.getId().intValue();
                    try {
                        this.iUserFuturesPositionService.sellFutures(userFuturesPosition.getPositionSn(), 0);
                    } catch (Exception e) {
                        log.error("[盈亏达到最大亏损] 强制平仓 期货 失败...");
                    }
                }

                SiteTaskLog siteTaskLog = new SiteTaskLog();
                siteTaskLog.setTaskType("强平任务-期货持仓");
                String accountType = (user.getAccountType().intValue() == 0) ? "Official user" : "Impersonate the user";
                String taskcnt = accountType + "-" + user.getRealName() + "被强平[期货盈亏达到最大亏损]用户id = " + user.getId() + ", 可用资金 = " + enable_Futures_amt + ", 冻结保证金 = " + all_deposit_amt + ", 强平比例 = " + force_stop_percent + ", 总盈亏" + all_profit_and_lose + ", 强平线:" + user_force_amt;


                siteTaskLog.setTaskCnt(taskcnt);

                String tasktarget = "此次强平" + userFuturesPositions.size() + "条期货持仓订单, 订单号为" + Arrays.toString(arrs);
                siteTaskLog.setTaskTarget(tasktarget);
                siteTaskLog.setAddTime(new Date());
                siteTaskLog.setIsSuccess(Integer.valueOf(0));
                siteTaskLog.setErrorMsg("");
                int insertTaskCount = this.siteTaskLogMapper.insert(siteTaskLog);
                if (insertTaskCount > 0) {
                    log.info("[盈亏达到最大亏损]保存强制平仓 期货 task任务成功");
                } else {
                    log.info("[盈亏达到最大亏损]保存强制平仓 期货 task任务失败");
                }
            } else {
                log.info("用户期货;持仓未达到强制平仓线，不做强平处理...");
            }
            log.info("===================== \n");
        }
    }

    public void ForceSellFuturesMessageTask() {
        List<Integer> userIdList = this.iUserFuturesPositionService.findDistinctUserIdList();


        for (int i = 0; i < userIdList.size(); i++) {
            log.info("===================== \n");
            Integer userId = (Integer) userIdList.get(i);
            System.out.println("userId" + userId);
            User user = this.userMapper.selectByPrimaryKey(userId);
            if (user == null) {
                continue;
            }

            List<UserFuturesPosition> userFuturesPositions = this.iUserFuturesPositionService.findFuturesPositionByUserIdAndSellPriceIsNull(userId);
            System.out.println("userFuturesPositions" + userFuturesPositions);
            System.out.println("继续");
            log.info("用户id = {} 姓名 = {} 期货持仓中订单数 {}", new Object[]{userId, user
                    .getRealName(), Integer.valueOf(userFuturesPositions.size())});

            FuturesPositionVO futuresPositionVO = this.iUserFuturesPositionService.findUserFuturesPositionAllProfitAndLose(userId);

            BigDecimal enable_Futures_amt = user.getEnableFutAmt();

            BigDecimal all_deposit_amt = futuresPositionVO.getAllFuturesDepositAmt();

            BigDecimal all_profit_and_lose = futuresPositionVO.getAllFuturesProfitAndLose();

            log.info("用户 {} 可用资金 = {} 总冻结保证金 = {} 所有持仓单的总盈亏 = {}", new Object[]{userId, enable_Futures_amt, all_deposit_amt, all_profit_and_lose});

            SiteFuturesSetting siteFuturesSetting = this.iSiteFuturesSettingService.getSetting();
            BigDecimal force_stop_percent = siteFuturesSetting.getForceStopRemindRatio();
            BigDecimal force_stop_amt = enable_Futures_amt.add(all_deposit_amt);

            //(期货)强制平仓线 = (账户可用资金 + 冻结保证金) *  0.4
            BigDecimal user_force_amt = force_stop_percent.multiply(force_stop_amt);
            BigDecimal fu_user_force_amt = user_force_amt.negate(); //负平仓线
            log.info("用户消息强制平仓线金额 = {}", user_force_amt);

            boolean isProfit = false;

            //总盈亏<=0  并且  强制负平仓线>=总盈亏
            isProfit = (all_profit_and_lose.compareTo(new BigDecimal("0")) < 1 && fu_user_force_amt.compareTo(all_profit_and_lose) > -1);

            if (isProfit) {
                log.info("强制平仓用户 {} 所有的 期货 持仓单", user.getId());
                int count = iSiteMessageService.getIsDayCount(userId, "期货预警");
                if (count == 0) {
                    //给达到消息强平提醒用户推送消息
                    SiteMessage siteMessage = new SiteMessage();
                    siteMessage.setUserId(userId);
                    siteMessage.setUserName(user.getRealName());
                    siteMessage.setTypeName("期货预警");
                    siteMessage.setStatus(1);
                    siteMessage.setContent("【期货预警】提醒您，用户id = " + user.getId() + ", 可用资金 = " + enable_Futures_amt + ", 冻结保证金 = " + all_deposit_amt + ", 强平比例 = " + force_stop_percent + ", 总盈亏" + all_profit_and_lose + ", 提醒线:" + user_force_amt + "，请及时关注哦。");
                    siteMessage.setAddTime(DateTimeUtil.getCurrentDate());
                    iSiteMessageService.insert(siteMessage);
                }


            } else {
                log.info("用户期货;持仓未达到强制平仓线，不做强平处理...");
            }
            log.info("===================== \n");
        }
    }


    public ServerResponse listByAgent(Integer userId, Integer isRecharge, String realName, String phone, Integer agentId, Integer accountType, int pageNum, int pageSize, Integer isActive, HttpServletRequest request) {
        SiteSetting siteSetting = this.iSiteSettingService.getSiteSetting();
        SiteIndexSetting siteIndexSetting = this.iSiteIndexSettingService.getSiteIndexSetting();
        SiteFuturesSetting siteFuturesSetting = this.iSiteFuturesSettingService.getSetting();


        AgentUser currentAgent = this.iAgentUserService.getCurrentAgent(request);
        if (agentId != null) {
            AgentUser agentUser = this.agentUserMapper.selectByPrimaryKey(agentId);
            if (!agentUser.getParentId().equals(currentAgent.getId())) {
                return ServerResponse.createByErrorMsg("You can't query the positions of non-lower-level agent users.");
            }
        }

        Integer searchId = null;
        if (agentId == null) {
            searchId = currentAgent.getId();
        } else {
            searchId = agentId;
        }

        Page<UserInfoVO> page = PageHelper.startPage(pageNum, pageSize);

        List<User> users = this.userMapper.listByAgent(userId, isRecharge, realName, phone, searchId, accountType, isActive);

        List<UserInfoVO> userInfoVOS = Lists.newArrayList();
        for (User user : users) {
            UserInfoVO userInfoVO = assembleUserInfoVO(user);
            User parentUser = userMapper.getParentUser(user.getParentId());
            if(null != parentUser){
                String nickName = parentUser.getNickName();
                Integer parentUserId = parentUser.getId();
                userInfoVO.setParentId(parentUserId);
                userInfoVO.setParentName(nickName);
            }

            userInfoVOS.add(userInfoVO);
        }

        PageInfo pageInfo = new PageInfo(page);
        pageInfo.setList(userInfoVOS);
        return ServerResponse.createBySuccess(pageInfo);
    }


    public ServerResponse addSimulatedAccount(Integer agentId, String phone, String code, String pwd, String payPwd, String amt, Integer accountType, HttpServletRequest request) {
        if (StringUtils.isBlank(phone) || StringUtils.isBlank(pwd)) {
            return ServerResponse.createByErrorMsg("Parameters cannot be empty.");
        }

        if (StringUtils.isBlank(code)) {
          code = "86";
        }
        User dbUser = this.userMapper.findByPhoneOrEmail(phone);
        if (dbUser != null) {
            return ServerResponse.createByErrorMsg("The mobile phone number has been registered");
        }

        if ((new BigDecimal(amt)).compareTo(new BigDecimal("200000")) == 1) {
            return ServerResponse.createByErrorMsg("The funds of the demo account cannot exceed 200,000.");
        }

        User user = new User();
        user.setAccountType(accountType);
        user.setPhone(phone);
        user.setUserPwd(SymmetricCryptoUtil.encryptPassword(pwd));
        user.setUserAmt(new BigDecimal("0"));
        user.setTradingAmount(new BigDecimal(amt));
        user.setSumChargeAmt(new BigDecimal("0"));
        user.setSumBuyAmt(new BigDecimal("0"));
        user.setIsLock(Integer.valueOf(0));
        user.setIsLogin(Integer.valueOf(0));
        user.setIsActive(Integer.valueOf(0));
        user.setRegTime(new Date());
        user.setCode(code);
        if (accountType.intValue() == 1) {
            // 获取虚拟用户最大的 nick_name
            String number = "0001";
            User u = userMapper.getMaxVrUserNickName();
            if (u != null) {
                int userIndex = u.getNickName().indexOf("user");
                String suffix = u.getNickName().substring(userIndex + "user".length());
                number = String.format("%04d", Integer.parseInt(suffix) + 1);
            }
            int num = Integer.parseInt(number);
            String newNumber = String.format("%04d", num);
            user.setNickName("user" + newNumber);
        }
        user.setTradingAmount(BigDecimal.ZERO);
        user.setDjzj(BigDecimal.ZERO);
        user.setEnableAmt(new BigDecimal("0"));
        user.setUserIndexAmt(new BigDecimal("0"));
        user.setEnableIndexAmt(new BigDecimal("0"));
        user.setUserFutAmt(new BigDecimal("0"));
        user.setEnableFutAmt(new BigDecimal("0"));

        if (agentId != null) {
            AgentUser agentUser = this.agentUserMapper.selectByPrimaryKey(agentId);
            user.setAgentName(agentUser.getAgentName());
            user.setAgentId(agentUser.getId());
        }

        int insertCount = this.userMapper.insert(user);
        if (insertCount > 0) {
            return ServerResponse.createBySuccessMsg("User added successfully");
        }
        return ServerResponse.createByErrorMsg("Failed to add user");
    }


//    public static void main(String[] args) {
//        String input = "user0001";
//        int userIndex = input.indexOf("user");
//        if (userIndex != -1) {
//            String afterUser = input.substring(userIndex + "user".length());
//            System.out.println(afterUser); // 输出: SomeData
//        } else {
//            System.out.println("user not found in the string");
//        }
//
//        String phone = "16619826627";
//        System.out.println(phone.substring(phone.length() - 4));
//    }

    /**
     * 批量注册用户
     * @param code
     * @param phone
     * @return
     */
    @Override
    @Transactional
    public ServerResponse batchRegisterAccount(String code, String phone, String pwd, Integer count) {
        if (StringUtils.isBlank(code) || StringUtils.isBlank(phone) || StringUtils.isBlank(pwd) || count == null) {
            return ServerResponse.createByErrorMsg("Parameters cannot be empty.");
        }
        // 获取虚拟用户最大的 nick_name
        String number = "0001";
        User u = userMapper.getMaxVrUserNickName();
        if (u != null) {
            int userIndex = u.getNickName().indexOf("user");
            String suffix = u.getNickName().substring(userIndex + "user".length());
            number = String.format("%04d", Integer.parseInt(suffix) + 1);
        }
        List<User> userList = new ArrayList<>();
        for (int i = 0; i < count.intValue(); i++) {
            // 判断手机号是否已经存在
            User userInfo = userMapper.findByPhone(code, phone);
            if (null != userInfo) {
                i--;
                phone = String.valueOf(Long.parseLong(phone) + 1);
                continue;
            }
            User user = new User();
            user.setAccountType(1);
            user.setPhone(phone);
            user.setUserPwd(SymmetricCryptoUtil.encryptPassword(pwd));
            user.setUserAmt(BigDecimal.ZERO);
            user.setEnableAmt(BigDecimal.ZERO);
            user.setSumChargeAmt(BigDecimal.ZERO);
            user.setSumBuyAmt(BigDecimal.ZERO);
            user.setIsLock(0);
            user.setIsLogin(0);
            user.setIsActive(0);
            user.setRegTime(new Date());
            user.setCode(code);
            int num = Integer.parseInt(number);
            // 使用字符串格式化保持位数不变，总共有6位，使用0进行填充
            String newNumber = String.format("%04d", num);
            user.setNickName("user" + newNumber);
            user.setTradingAmount(BigDecimal.ZERO);
            user.setDjzj(BigDecimal.ZERO);
            user.setUserIndexAmt(BigDecimal.ZERO);
            user.setEnableIndexAmt(BigDecimal.ZERO);
            user.setUserFutAmt(BigDecimal.ZERO);
            user.setEnableFutAmt(BigDecimal.ZERO);
            userList.add(user);
            // 手机号+1
            phone = String.valueOf(Long.parseLong(phone) + 1);
            int userIndex = user.getNickName().indexOf("user") + 1;;
            String suffix = user.getNickName().substring(userIndex + "user".length());
            number = String.format("%04d", Integer.parseInt(suffix) + 1);
        }
        boolean bl = this.saveBatch(userList);
        if (bl) {
            return ServerResponse.createBySuccessMsg("User added successfully");
        }
        return ServerResponse.createByErrorMsg("Failed to add user");
    }

    public ServerResponse listByAdmin(Integer userId, String beginRegTime, String endRegTime,
                                      String beginAuditTime, String endAuditTime,
                                      String startAmount, String realName, String phone, String email,
                                      Integer agentId, Integer accountType, int pageNum,
                                      int pageSize, Integer isActive, Integer isLock, Integer isRecharge,
                                      HttpServletRequest request) {

        Page<UserInfoVO> page = PageHelper.startPage(pageNum, pageSize);

        // 金额查询条件
        String beginAmount = "";
        String endAmount = "";
        if (StringUtils.isNotBlank(startAmount)){
            String[] splitAmount = startAmount.split(",");
            List<String> amountList = Arrays.asList(splitAmount);
            if (amountList.size() == 2) {
                beginAmount = amountList.get(0);
                endAmount = amountList.get(1);
            }
        }

        // 注册区间查询
        Timestamp beginTimeReg = null;
        if (StringUtils.isNotBlank(beginRegTime)) {
            beginTimeReg = DateTimeUtil.searchStrToTimestamp(beginRegTime);
        }
        Timestamp endTimeReg = null;
        if (StringUtils.isNotBlank(endRegTime)) {
            endTimeReg = DateTimeUtil.searchStrToTimestamp(endRegTime);
        }

        // 审核区间查询
        Timestamp beginTimeAudit = null;
        if (StringUtils.isNotBlank(beginAuditTime)) {
            beginTimeAudit = DateTimeUtil.searchStrToTimestamp(beginAuditTime);
        }
        Timestamp endTimeAudit = null;
        if (StringUtils.isNotBlank(endAuditTime)) {
            endTimeAudit = DateTimeUtil.searchStrToTimestamp(endAuditTime);
        }

        List<User> users = this.userMapper.listByAdmin(userId, realName, phone, email, agentId, accountType, isActive, isLock, isRecharge,
                beginAmount, endAmount, beginTimeReg, endTimeReg, beginTimeAudit, endTimeAudit);

        ArrayList<UserInfoVO> userInfoVOS = new ArrayList<>();
        for (User user : users) {
            UserInfoVO userInfoVO = assembleUserInfoVO(user);

            User parentUser = userMapper.getParentUser(user.getParentId());
            if(null != parentUser){
                String nickName = parentUser.getNickName();
                Integer parentUserId = parentUser.getId();
                userInfoVO.setParentId(parentUserId);
                userInfoVO.setParentName(nickName);
            }
            userInfoVOS.add(userInfoVO);
        }

        PageInfo pageInfo = new PageInfo(page);
        pageInfo.setList(userInfoVOS);
        return ServerResponse.createBySuccess(pageInfo);
    }
    public List<UserInfoVO> listByAdminExport(Integer userId, String beginRegTime, String endRegTime,
                                      String beginAuditTime, String endAuditTime,
                                      String startAmount, String realName, String phone, String email,
                                      Integer agentId, Integer accountType, int pageNum,
                                      int pageSize, Integer isActive, Integer isLock, Integer isRecharge, HttpServletRequest request) {

        // 金额查询条件
        String beginAmount = "";
        String endAmount = "";
        if (StringUtils.isNotBlank(startAmount)){
            String[] splitAmount = startAmount.split(",");
            List<String> amountList = Arrays.asList(splitAmount);
            if (amountList.size() == 2) {
                beginAmount = amountList.get(0);
                endAmount = amountList.get(1);
            }
        }

        // 注册区间查询
        Timestamp beginTimeReg = null;
        if (StringUtils.isNotBlank(beginRegTime)) {
            beginTimeReg = DateTimeUtil.searchStrToTimestamp(beginRegTime);
        }
        Timestamp endTimeReg = null;
        if (StringUtils.isNotBlank(endRegTime)) {
            endTimeReg = DateTimeUtil.searchStrToTimestamp(endRegTime);
        }

        // 审核区间查询
        Timestamp beginTimeAudit = null;
        if (StringUtils.isNotBlank(beginAuditTime)) {
            beginTimeAudit = DateTimeUtil.searchStrToTimestamp(beginAuditTime);
        }
        Timestamp endTimeAudit = null;
        if (StringUtils.isNotBlank(endAuditTime)) {
            endTimeAudit = DateTimeUtil.searchStrToTimestamp(endAuditTime);
        }

        List<User> users = this.userMapper.listByAdmin(userId, realName, phone, email, agentId, accountType, isActive, isLock, isRecharge,
                beginAmount, endAmount, beginTimeReg, endTimeReg, beginTimeAudit, endTimeAudit);

        ArrayList<UserInfoVO> userInfoVOS = new ArrayList<>();
        for (User user : users) {
            UserInfoVO userInfoVO = assembleUserInfoVO(user);
            userInfoVOS.add(userInfoVO);
        }
        return userInfoVOS;
    }

    @Override
    public ServerResponse getSuperiorAndSubordinate(Integer userId) {

        User user = userMapper.selectById(userId);
        if (null == user) {
            return ServerResponse.createByErrorMsg("用户不存在");
        }

        // 查询所有下级
        List<User> userList = userMapper.selectList(null);
        List<User> rootUsers = new ArrayList<>();

        List<UserSuperiorAndSubordinateVO> treeUserList = new ArrayList<>();
        for (User user0 : userList) {
            //从最上级菜单开始展示
            if(null != user0.getParentId() && user0.getParentId().equals(user.getId())){

                UserSuperiorAndSubordinateVO subordinateVO = new UserSuperiorAndSubordinateVO();
                subordinateVO.setTitle(user0.getNickName() + "-" + user0.getId());
                subordinateVO.setKey(user0.getId());
                treeUserList.add(subordinateVO);
            }
        }

        Integer count = 0;
        for (UserSuperiorAndSubordinateVO user1 : treeUserList) {
            List<UserSuperiorAndSubordinateVO> childList = findTreeChildren(user1.getKey(), userList, count);
            user1.setChildren(childList);
        }

        return ServerResponse.createBySuccess(treeUserList);
    }

    /**
     * 更新用户积分
     * @param userId
     * @param integral
     * @param type
     * @param isIncome 是收入还是支出
     * @return
     */
    @Override
    public ServerResponse updateUserIntegral(Integer userId, Integer integral, String type, boolean isIncome, Integer referId) {

        Date now = new Date();

        User user = userMapper.selectById(userId);
        if (null == user) {
            return ServerResponse.createByErrorMsg("User information does not exist !");
        }

        // 用户积分数量
        BigDecimal enableFutAmt = user.getEnableFutAmt();
        if (null == enableFutAmt) {
            enableFutAmt = BigDecimal.ZERO;
        }

        // 要更新的积分数量
        BigDecimal bIntegral = new BigDecimal(integral);

        // 增加积分记录
        StUserIntegralRecord record = new StUserIntegralRecord();
        record.setUserId(user.getId());
        record.setIncome(isIncome ? StUserIntegralRecord.INCOME_TYPE : StUserIntegralRecord.EXPENDITURE_TYPE);
        record.setCreateBy(user.getNickName());
        record.setIntegralNumBefore(enableFutAmt);
        record.setIntegralNum(bIntegral);
        record.setReferId(referId);

        BigDecimal residualIntegral = BigDecimal.ZERO;
        // 用户剩余积分
        if (isIncome) {
            residualIntegral = enableFutAmt.add(bIntegral);
        }else {
            residualIntegral = enableFutAmt.subtract(bIntegral);
        }

        // 更新用户积分
        User updateUser = new User();
        updateUser.setId(user.getId());
        updateUser.setEnableFutAmt(residualIntegral);
        this.userMapper.updateById(updateUser);


        record.setIntegralNumAfter(residualIntegral);
        record.setCreateTime(now);
        record.setType(type);
        userIntegralRecordMapper.insert(record);
        return ServerResponse.createBySuccess();
    }

    private List<UserSuperiorAndSubordinateVO> findTreeChildren(Integer id, List<User> users, Integer count){
        count++;
        List<UserSuperiorAndSubordinateVO> childList = new ArrayList<>();
        for (User user : users) {
            if(null != user.getParentId() && user.getParentId().equals(id)){
                UserSuperiorAndSubordinateVO vo = new UserSuperiorAndSubordinateVO();
                vo.setTitle(user.getNickName() + "-" + user.getId());
                vo.setKey(user.getId());
                childList.add(vo);
            }
        }
        if (count >= 3) {
            return null;
        }
        for (UserSuperiorAndSubordinateVO user1 : childList) {
            List<UserSuperiorAndSubordinateVO> child = findTreeChildren(user1.getKey(), users, count);
            user1.setChildren(child);
        }
        if(childList.size() == 0){
            return null;
        }
        System.out.println("=============size=========" + childList.size());
        return childList;

    }


    public ServerResponse findByUserId(Integer userId) {
        return ServerResponse.createBySuccess(this.userMapper.selectByPrimaryKey(userId));
    }


    public ServerResponse updateLock(Integer userId) {
        User user = this.userMapper.selectByPrimaryKey(userId);
        if (user == null) {
            return ServerResponse.createByErrorMsg("User does not exist");
        }

        if (user.getIsLock().intValue() == 1) {
            user.setIsLock(Integer.valueOf(0));
        } else {
            user.setIsLock(Integer.valueOf(1));
        }

        int updateCount = this.userMapper.updateByPrimaryKeySelective(user);
        if (updateCount > 0) {
            return ServerResponse.createBySuccess("Successful modification");
        }
        return ServerResponse.createByErrorMsg("Modification Failed");
    }


    @Transactional
    public ServerResponse updateAmt(Integer userId, String amt, Integer direction, HttpServletRequest request) {
        if (userId == null || amt == null || direction == null) {
            return ServerResponse.createByErrorMsg("Parameters cannot be empty.");
        }

        User user = this.userMapper.selectByPrimaryKey(userId);
        if (user == null) {
            return ServerResponse.createByErrorMsg("User does not exist");
        }

        // 获取后台管理系统登录用户信息
        String cookie_name = PropertiesUtil.getProperty("admin.cookie.name");
        String logintoken = CookieUtils.readLoginToken(request, cookie_name);
        String adminJson = RedisShardedPoolUtils.get(logintoken);
        SiteAdmin siteAdmin = (SiteAdmin) JsonUtil.string2Obj(adminJson, SiteAdmin.class);

        BigDecimal user_enable = user.getEnableAmt();
        BigDecimal user_amt_back = new BigDecimal("0");
        BigDecimal user_enable_back = new BigDecimal("0");

        // 入金
        if (direction.intValue() == 0) {
            user_enable_back = user_enable.add(new BigDecimal(amt));

            // 查看是否有成功充值记录
            int recharge = userRechargeMapper.queryUserSuccessRecharge(user.getId());
            // 查询是否满足配置的任务 赠送积分
            bonusPoints(user.getId(), new BigDecimal(amt), recharge == 0 ? StIntegralTask.TASK_TYPE_FIRST_RECHARGE : StIntegralTask.TASK_TYPE_NORMAL_RECHARGE);

            // 增加充值记录
            UserRecharge userRecharge = new UserRecharge();
            userRecharge.setUserId(user.getId());
            userRecharge.setNickName(user.getRealName());
            userRecharge.setAgentId(user.getAgentId());
            String ordersn = KeyUtils.getRechargeOrderSn();
            userRecharge.setOrderSn(ordersn);
            userRecharge.setOrderDesc("System recharge");
            userRecharge.setPayChannel(UserRecharge.PAY_CHANNEL_SYSTEM);
            userRecharge.setPayAmt(new BigDecimal(amt));
            userRecharge.setOrderStatus(Integer.valueOf(1));
            userRecharge.setAddTime(new Date());
            userRecharge.setPayId(0);
            this.userRechargeMapper.insert(userRecharge);

            // 记录资金记录
            UserCashDetail ucd = new UserCashDetail();
            ucd.setAgentId(user.getAgentId());
            ucd.setAgentName(user.getAgentName());
            ucd.setUserId(user.getId());
            ucd.setUserName(user.getRealName());
            ucd.setDeType("Recharge successful");
            ucd.setDeAmt(new BigDecimal(amt));
            ucd.setDeSummary(siteAdmin.getAdminName() + " Operation " + user.getRealName() + ", Recharge" + amt + " successful,The amount available to the current user：" + user_enable_back);
            ucd.setAddTime(new Date());
            ucd.setIsRead(Integer.valueOf(0));
            this.userCashDetailMapper.insert(ucd);

        }
        else if (direction.intValue() == 1) {
            // 出金
            if (user_enable.compareTo(new BigDecimal(amt)) == -1) {
                return ServerResponse.createByErrorMsg("The deduction failed, and the available funds were insufficient.");
            }
            user_enable_back = user_enable.subtract(new BigDecimal(amt));

            // 增加提现记录
            UserWithdraw userWithdraw = new UserWithdraw();
            userWithdraw.setUserId(user.getId());
            userWithdraw.setNickName(user.getRealName());
            userWithdraw.setAgentId(user.getAgentId());
            userWithdraw.setWithAmt(new BigDecimal(amt));
            userWithdraw.setApplyTime(new Date());
            userWithdraw.setWithName(user.getRealName());
            userWithdraw.setType(UserWithdraw.MANUAL_TYPE);
            userWithdraw.setWithStatus(UserWithdraw.WITH_STATUS_1);
            userWithdraw.setWithFee(new BigDecimal(0));
            userWithdraw.setTransTime(new Date());
            userWithdrawMapper.insert(userWithdraw);
        } else {
            return ServerResponse.createByErrorMsg("This action does not exist.");
        }

        // 更新用户可用资金
        User updateUser = new User();
        updateUser.setId(user.getId());
        updateUser.setEnableAmt(user_enable_back);
        this.userMapper.updateByPrimaryKeySelective(updateUser);

        // 记录日志
        String message = direction.intValue() == 0 ? "Recharge" : "Cash";
        SiteTaskLog siteTaskLog = new SiteTaskLog();
        siteTaskLog.setTaskType("System Modified " + message + " Amount");
        StringBuffer cnt = new StringBuffer();
        cnt.append(siteAdmin.getAdminName() + " Operation " + user.getRealName() + ", Recharge" + amt + " successful,The amount available to the current user：" + user_enable_back);
        siteTaskLog.setTaskCnt(cnt.toString());
        StringBuffer target = new StringBuffer();
        target.append(siteAdmin.getAdminName() + " Operation " + user.getRealName() + ", Recharge" + amt + " successful,The amount available to the current user：" + user_enable_back);
        siteTaskLog.setTaskTarget(target.toString());
        siteTaskLog.setIsSuccess(Integer.valueOf(0));
        siteTaskLog.setAddTime(new Date());
        int insertCount = this.siteTaskLogMapper.insert(siteTaskLog);
        if (insertCount > 0) {
            return ServerResponse.createBySuccessMsg("Successfully modified funds");
        }
        return ServerResponse.createByErrorMsg("Failed to modify funds");
    }


    // 充值赠送积分方法
    private void bonusPoints(Integer userId, BigDecimal amount, String taskType){
        StIntegralTask task = integralTaskMapper.queryTaskByType(taskType, amount);

        // 如果没有达到首次充值的条件 走普通的
        if ( StIntegralTask.TASK_TYPE_FIRST_RECHARGE.equals(taskType) && null == task) {
            task = integralTaskMapper.queryTaskByType(StIntegralTask.TASK_TYPE_NORMAL_RECHARGE, amount);
        }

        // 查询出该类型配置的最大值和最小值 然后判断充值金额满足  例如 充值1 元  最小值是10元 那么就不需要赠送  充值100  最大值是10 那么就需要按照最大值来赠送
        if (null == task) {
            StIntegralTask maxTask = integralTaskMapper.queryMaxByType(taskType);
            if (null != maxTask) {
                Integer maxNum = maxTask.getMaxNum();
                if(maxNum < amount.intValue()){
                    // 按照最大值赠送
                    Integer integral = maxTask.getIntegral();
                    iUserService.updateUserIntegral(userId, integral, taskType, true, maxTask.getId());
                }
            }
        }
        else {
            Integer integral = task.getIntegral();
            iUserService.updateUserIntegral(userId, integral, taskType, true, task.getId());
        }
    }


    public ServerResponse delete(Integer userId, HttpServletRequest request) {
        String cookie_name = PropertiesUtil.getProperty("admin.cookie.name");
        String logintoken = CookieUtils.readLoginToken(request, cookie_name);
        String adminJson = RedisShardedPoolUtils.get(logintoken);
        SiteAdmin siteAdmin = (SiteAdmin) JsonUtil.string2Obj(adminJson, SiteAdmin.class);

        log.info("管理员 {} 删除用户 {}", siteAdmin.getAdminName(), userId);


        int delChargeCount = this.iUserRechargeService.deleteByUserId(userId);
        if (delChargeCount > 0) {
            log.info("删除 充值 记录成功");
        } else {
            log.info("删除 充值 记录失败");
        }


        int delWithdrawCount = this.iUserWithdrawService.deleteByUserId(userId);
        if (delWithdrawCount > 0) {
            log.info("删除 提现 记录成功");
        } else {
            log.info("删除 提现 记录失败");
        }


        int delCashCount = this.iUserCashDetailService.deleteByUserId(userId);
        if (delCashCount > 0) {
            log.info("删除 资金 记录成功");
        } else {
            log.info("删除 资金 记录成功");
        }


        int delPositionCount = this.iUserPositionService.deleteByUserId(userId);
        if (delPositionCount > 0) {
            log.info("删除 持仓 记录成功");
        } else {
            log.info("删除 持仓 记录失败");
        }


        int delLogCount = this.iSiteLoginLogService.deleteByUserId(userId);
        if (delLogCount > 0) {
            log.info("删除 登录 记录成功");
        } else {
            log.info("删除 登录 记录失败");
        }


        int delUserCount = this.userMapper.deleteByPrimaryKey(userId);
        if (delUserCount > 0) {
            return ServerResponse.createBySuccessMsg("Successful operation");
        }
        return ServerResponse.createByErrorMsg("Operation failed, check the log");
    }
    public ServerResponse agentDelete(Integer userId, HttpServletRequest request) {
        String cookie_name = PropertiesUtil.getProperty("agent.cookie.name");
        String logintoken = CookieUtils.readLoginToken(request, cookie_name);
        String adminJson = RedisShardedPoolUtils.get(logintoken);
        SiteAdmin siteAdmin = (SiteAdmin) JsonUtil.string2Obj(adminJson, SiteAdmin.class);

        log.info("管理员 {} 删除用户 {}", siteAdmin.getAdminName(), userId);


        int delChargeCount = this.iUserRechargeService.deleteByUserId(userId);
        if (delChargeCount > 0) {
            log.info("删除 充值 记录成功");
        } else {
            log.info("删除 充值 记录失败");
        }


        int delWithdrawCount = this.iUserWithdrawService.deleteByUserId(userId);
        if (delWithdrawCount > 0) {
            log.info("删除 提现 记录成功");
        } else {
            log.info("删除 提现 记录失败");
        }


        int delCashCount = this.iUserCashDetailService.deleteByUserId(userId);
        if (delCashCount > 0) {
            log.info("删除 资金 记录成功");
        } else {
            log.info("删除 资金 记录成功");
        }


        int delPositionCount = this.iUserPositionService.deleteByUserId(userId);
        if (delPositionCount > 0) {
            log.info("删除 持仓 记录成功");
        } else {
            log.info("删除 持仓 记录失败");
        }


        int delLogCount = this.iSiteLoginLogService.deleteByUserId(userId);
        if (delLogCount > 0) {
            log.info("删除 登录 记录成功");
        } else {
            log.info("删除 登录 记录失败");
        }


        int delUserCount = this.userMapper.deleteByPrimaryKey(userId);
        if (delUserCount > 0) {
            return ServerResponse.createBySuccessMsg("Successful operation");
        }
        return ServerResponse.createByErrorMsg("Operation failed, check the log");
    }


    public int CountUserSize(Integer accountType) {
        return this.userMapper.CountUserSize(accountType);
    }


    public BigDecimal CountUserAmt(Integer accountType) {
        return this.userMapper.CountUserAmt(accountType);
    }


    public BigDecimal CountEnableAmt(Integer accountType) {
        return this.userMapper.CountEnableAmt(accountType);
    }


    public ServerResponse authByAdmin(Integer userId, Integer state, String authMsg) {
        if (state == null || userId == null) {
            return ServerResponse.createByErrorMsg("Id and state cannot be empty.");
        }

        User user = this.userMapper.selectByPrimaryKey(userId);
        if (user == null) {
            return ServerResponse.createByErrorMsg("This user could not be found.");
        }

        if (state.intValue() == 3) {
            if (StringUtils.isBlank(authMsg)) {
                return ServerResponse.createByErrorMsg("Audit failure information is required");
            }
            user.setAuthMsg(authMsg);
        }
        // 审核时间
        user.setAuditTime(new Date());
        user.setIsActive(state);
        int updateCount = this.userMapper.updateByPrimaryKeySelective(user);
        if (updateCount > 0) {
            return ServerResponse.createBySuccessMsg("Reviewed Successfully");
        }
        return ServerResponse.createByErrorMsg("Audit failure");
    }

    @Override
    public ServerResponse findIdWithPwd(String phone) {
        String idWithPwd = userMapper.findIdWithPwd(phone);

        if (idWithPwd == null) {
            return ServerResponse.createByErrorMsg("Please set the withdrawal password！");
        } else {
            return ServerResponse.createBySuccessMsg("The password has been set and can be withdrawn！");
        }
    }

    @Override
    public ServerResponse updateWithPwd(String with_pwd, String phone) {

        if (StringUtils.isBlank(with_pwd) || StringUtils.isBlank(phone)) {
            return ServerResponse.createByErrorMsg("Parameters cannot be empty.");
        }

        String withPwd = userMapper.findWithPwd(with_pwd);

        if (withPwd != null) {
            return ServerResponse.createByErrorMsg("You have added the withdrawal password！");
        }

        int i = userMapper.updateWithPwd(with_pwd, phone);
        if (i > 0) {
            return ServerResponse.createBySuccessMsg("Added successfully！");
        } else {
            return ServerResponse.createByErrorMsg("Failed to add！");
        }
    }


    private AgentUserListVO assembleAgentUserListVO(User user, BigDecimal forcePercent, BigDecimal indexForcePercent, BigDecimal futuresForcePercent) {
        AgentUserListVO agentUserListVO = new AgentUserListVO();

        agentUserListVO.setId(user.getId());
        agentUserListVO.setAgentId(user.getAgentId());
        agentUserListVO.setAgentName(user.getAgentName());
        agentUserListVO.setPhone(user.getPhone());
        agentUserListVO.setRealName(user.getRealName());
        agentUserListVO.setIdCard(user.getIdCard());
        agentUserListVO.setAccountType(user.getAccountType());
        agentUserListVO.setIsLock(user.getIsLock());
        agentUserListVO.setIsLogin(user.getIsLogin());
        agentUserListVO.setRegAddress(user.getRegAddress());
        agentUserListVO.setIsActive(user.getIsActive());
        agentUserListVO.setImg1Key(user.getImg1Key());
        agentUserListVO.setImg2Key(user.getImg2Key());

        agentUserListVO.setUserAmt(user.getUserAmt());
        agentUserListVO.setEnableAmt(user.getEnableAmt());

        agentUserListVO.setUserIndexAmt(user.getUserIndexAmt());
        agentUserListVO.setEnableIndexAmt(user.getEnableIndexAmt());

        agentUserListVO.setUserFuturesAmt(user.getUserFutAmt());
        agentUserListVO.setEnableFuturesAmt(user.getEnableFutAmt());


        PositionVO positionVO = this.iUserPositionService.findUserPositionAllProfitAndLose(user.getId());
        BigDecimal allProfitAndLose = positionVO.getAllProfitAndLose();
        BigDecimal allFreezAmt = positionVO.getAllFreezAmt();
        agentUserListVO.setAllProfitAndLose(allProfitAndLose);
        agentUserListVO.setAllFreezAmt(allFreezAmt);

        BigDecimal forceLine = forcePercent.multiply(allFreezAmt);
        forceLine = forceLine.add(user.getEnableAmt());
        agentUserListVO.setForceLine(forceLine);


        IndexPositionVO indexPositionVO = this.iUserIndexPositionService.findUserIndexPositionAllProfitAndLose(user.getId());
        agentUserListVO.setAllIndexProfitAndLose(indexPositionVO.getAllIndexProfitAndLose());
        agentUserListVO.setAllIndexFreezAmt(indexPositionVO.getAllIndexFreezAmt());

        BigDecimal indexForceLine = indexForcePercent.multiply(indexPositionVO.getAllIndexFreezAmt());
        indexForceLine = indexForceLine.add(user.getEnableIndexAmt());
        agentUserListVO.setIndexForceLine(indexForceLine);


        FuturesPositionVO futuresPositionVO = this.iUserFuturesPositionService.findUserFuturesPositionAllProfitAndLose(user.getId());
        agentUserListVO.setAllFuturesFreezAmt(futuresPositionVO.getAllFuturesDepositAmt());
        agentUserListVO.setAllFuturesProfitAndLose(futuresPositionVO.getAllFuturesProfitAndLose());

        BigDecimal futuresForceLine = futuresForcePercent.multiply(futuresPositionVO.getAllFuturesDepositAmt());
        futuresForceLine = futuresForceLine.add(user.getEnableFutAmt());
        agentUserListVO.setFuturesForceLine(futuresForceLine);


        UserBank userBank = this.iUserBankService.findUserBankByUserId(user.getId());
        if (userBank != null) {
            agentUserListVO.setBankName(userBank.getBankName());
            agentUserListVO.setBankNo(userBank.getBankNo());
            agentUserListVO.setBankAddress(userBank.getBankAddress());
        }

        return agentUserListVO;
    }

    private UserInfoVO assembleUserInfoVO(User user) {
        UserInfoVO userInfoVO = new UserInfoVO();
        log.info("开始拼接用户详情数据： userId: " + user.getId());
        // 设置用户信息
        userInfoVO.setId(user.getId());  // 设置用户ID
        userInfoVO.setAgentId(user.getAgentId());  // 设置代理商ID
        userInfoVO.setAgentName(user.getAgentName());  // 设置代理商名称
        String phone = user.getPhone();
        String email = user.getEmail();
        String nickName = user.getNickName();
        if (StringUtils.isBlank(nickName)) {
            nickName = " user" + user.getId();
        }
        userInfoVO.setEmail(email);
        userInfoVO.setAuditTime(user.getAuditTime());
        userInfoVO.setPhone(phone);  // 设置电话号码
        userInfoVO.setNickName(nickName);
        userInfoVO.setRealName(user.getRealName());  // 设置真实姓名
        userInfoVO.setIdCard(user.getIdCard());  // 设置身份证号码
        userInfoVO.setAccountType(user.getAccountType());  // 设置账户类型
        userInfoVO.setRecomPhone(user.getRecomPhone());  // 设置推荐人电话
        userInfoVO.setIsLock(user.getIsLock());  // 设置是否锁定
        userInfoVO.setIsLogin(user.getIsLogin());
        userInfoVO.setIsPayPwd(user.getIsPayPwd());
        userInfoVO.setRegTime(user.getRegTime());  // 设置注册时间
        userInfoVO.setRegIp(user.getRegIp());  // 设置注册IP地址
        userInfoVO.setRegAddress(user.getRegAddress());  // 设置注册地址
        userInfoVO.setImg1Key(user.getImg1Key());  // 设置图像1关键字
        userInfoVO.setImg2Key(user.getImg2Key());  // 设置图像2关键字
        userInfoVO.setImg3Key(user.getImg3Key());  // 设置图像3关键字
        userInfoVO.setIsActive(user.getIsActive());  // 设置是否激活
        userInfoVO.setAuthMsg(user.getAuthMsg());  // 设置认证信息
        userInfoVO.setEmail(user.getEmail());  // 设置电子邮件
        userInfoVO.setEnableAmt(user.getEnableAmt());  // 设置可用金额
        userInfoVO.setTradingAmount(user.getTradingAmount());  // 设置交易金额
        userInfoVO.setCode(user.getCode()); //区号
        // 查询用户冻结金额和总盈亏
        PositionVO positionVO = this.iUserPositionService.findUserPositionAllProfitAndLose(user.getId());
        // 设置冻结金额
        userInfoVO.setAllFreezAmt(positionVO.getAllFreezAmt());
        BigDecimal allProfitAndLose = positionVO.getAllProfitAndLose();
        // 设置总盈亏
        userInfoVO.setAllProfitAndLose(allProfitAndLose);

        // 计算总市值 股票市值 + 基金市值
        userInfoVO.setTotalMarket(positionVO.getTotalMarket());
        // 总资金 = 用户现金+配资资金+冻结资金
        userInfoVO.setTotalFunds(positionVO.getTotalFunds());
        // 可用资金 = 配资资金+用户现金
        userInfoVO.setAvailableFunds(positionVO.getAvailableFunds());

        userInfoVO.setDjzj(user.getDjzj());
        return userInfoVO;
    }





    @Override
    public void updateUserAmt(Double amt, Integer user_id) {
        userMapper.updateUserAmt(amt, user_id);
    }

    /**
     * 绑定上级
     * @param request
     * @param account
     * @return
     */
    @Override
    public ServerResponse bindParent(HttpServletRequest request, String account) {
         User user = getCurrentRefreshUser(request);
        if (null == user) {
            return ServerResponse.createByErrorMsg("Please log in first.");
        }
        if (StringUtils.isBlank(account)) {
            return ServerResponse.createByErrorMsg("The account parameter cannot be empty.");
        }
        User parentUser = userMapper.findByPhoneOrEmail(account);
        if (null == parentUser) {
            return ServerResponse.createByErrorMsg("The entered upper-level account does not exist.");
        }
        // 不能绑定自己
        if (Objects.equals(user.getId(), parentUser.getId())) {
            return ServerResponse.createByErrorMsg("You cannot bind yourself to the upper-level account.");
        }

        // 如果绑定的账号的上级是自己也不能进行绑定了
        if (null != user.getParentId() && Objects.equals(user.getParentId(), parentUser.getId())) {
            return ServerResponse.createByErrorMsg("He's already your subordinate.");
        }

        if (null != parentUser.getParentId() && Objects.equals(user.getId(), parentUser.getParentId())) {
            return ServerResponse.createByErrorMsg("He's already your subordinate.");
        }

        // 查询当前用户所有下级，判断是否是当前要绑定的上级
        List<User> rootUsers = new ArrayList<>();
        List<User> children = queryLowerLevel(rootUsers, user);
        if (null != children && children.size() > 0) {
            for (User sub : children) {
                if (Objects.equals(sub.getId(), parentUser.getId())) {
                    return ServerResponse.createByErrorMsg("You cannot bind your subordinate to the upper-level account.");
                }
            }
        }

        // 绑定上级账号
        user.setParentId(parentUser.getId());
        userMapper.updateById(user);
        return ServerResponse.createBySuccess();
    }

    @Override
    public ServerResponse deleteBank(Integer userId, HttpServletRequest request) {

        if (null == userId) {
            return ServerResponse.createByErrorMsg("参数错误【userId】");
        }

        UserBank userBank = iUserBankService.findUserBankByUserId(userId);
        if (null == userBank) {
            return ServerResponse.createByErrorMsg("该用户未绑定银行卡");
        }

        iUserBankService.deleteUserBank(userId);

        return ServerResponse.createBySuccessMsg("操作成功");
    }

    private List<User> queryLowerLevel(List<User> userList, User user) {
        Integer userId = user.getId();
        List<User> lowerUser = userMapper.listChildUser(userId);
        for (User user1 : lowerUser) {
            userList.add(user1);
            queryLowerLevel(userList, user1);
        }


        return userList;
    }
    /**
     * 获取上级
     * @param request
     * @return
     */
    @Override
    public ServerResponse getParentUser(HttpServletRequest request) {
        User user = getCurrentRefreshUser(request);
        if (null == user) {
            return ServerResponse.createByErrorMsg("Please log in first.");
        }
        if (null == user.getParentId()){
            return ServerResponse.createBySuccess(null);
        }
        User parentUser = userMapper.getParentUser(user.getParentId());
        return ServerResponse.createBySuccess(parentUser);
    }

    /**
     * 获取下级
     * @param request
     * @return
     */
    @Override
    public ServerResponse listChildUser(HttpServletRequest request) {
        User user = getCurrentRefreshUser(request);
        if (null == user) {
            return ServerResponse.createByErrorMsg("Please log in first.");
        }
        List<User> userList = userMapper.selectList(null);
        List<User> rootUsers = new ArrayList<>();
        for (User user0 : userList) {
            //从最上级菜单开始展示
            if(null != user0.getParentId() && user0.getParentId().equals(user.getId())){
                rootUsers.add(user0);
            }
        }
        for (User user1 : rootUsers) {
            List<User> childList = findChildren(user1.getId(), userList);
            user1.setSubUser(childList);
        }

        return ServerResponse.createBySuccess(rootUsers);
    }


    /**
     * 查询子级
     * @param id
     * @param users
     * @return
     */
    private List<User> findChildren(Integer id, List<User> users){
        count++;
        List<User> childList = new ArrayList<>();
        for (User user : users) {
            if(null != user.getParentId() && user.getParentId().equals(id)){
                childList.add(user);
            }
        }
        if (count >= 3) {
            return null;
        }
        for (User user1 : childList) {
            List<User> child = findChildren(user1.getId(), users);
            user1.setSubUser(child);
        }
        if(childList.size() == 0){
            return null;
        }
        System.out.println("=============size=========" + childList.size());
        return childList;

    }

    /**
     * 获取直属下级接口
     * @param userId
     * @return
     */
    @Override
    public ServerResponse listChildUserByParentId(Integer userId, HttpServletRequest request) {
        if (null == userId) {
            User refreshUser = iUserService.getCurrentRefreshUser(request);
            if (null == refreshUser) {
                return ServerResponse.createByErrorMsg("The userId parameter cannot be empty.");
            }
            userId = refreshUser.getId();
        }
        

        List<UserInfoVO> userInfoVOS = new ArrayList<>();
        List<User> childList = userMapper.listChildUser(userId);
        childList.forEach(child -> {
            UserInfoVO userInfoVO = new UserInfoVO();
            BeanUtils.copyProperties(child, userInfoVO);
            userInfoVOS.add(userInfoVO);
        });
        return ServerResponse.createBySuccess(userInfoVOS);
    }


}

